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