I'm learning how to use conditional noexcept and come across this problem. Suppose I have a class:
template<typename T>
class Wrapper {
public:
Wrapper(T&& value) noexcept(/* ??? */)
: value_(std::move(value))
{}
private:
T value_;
};
For the /* ??? */ part, I thought we can use either noexcept(T(std::move(value))) or std::is_nothrow_move_constructible<T>::value, until I stumbled upon this.
So if I use noexcept(noexcept(T(std::move(value)))), strictly speaking I'm saying that "this constructor is noexcept iff constructing and destructing a T is noexcept"?
Although destructors that throw should be put on fire and burned.
Good question, see also this language defect discussion. From its name it appears clear that std::is_nothrow_move_constructible<T>::value should only relate to the constructibiliry from an rvalue (but in practice may also relate to the destruction), while noexcept(T(std::move(value))) always relates to both construction and destruction.
So, in your case, the most save way, avoiding the unresolved issue of the std::is_nothrow_move_constructible traits, is to use placement new, avoiding the issue with std::bad_alloc (mentioned in Chris Beck's comment), and, similarly, use T's desctructor for the wrapper's destructor.
template<typename T>
class Wrapper {
public:
Wrapper(T&& value) noexcept(new(nullptr) T(std::move(value)))
: value_(std::move(value))
{}
~Wrapper() noexcept(noexcept(value_.T::~T()))
{}
private:
T value_;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With