Good question, see also discussion of this language defect . From its name, it becomes clear that std::is_nothrow_move_constructible<T>::value should relate only to constructivity from rvalue (but in practice it can also relate to destruction), and noexcept(T(std::move(value))) always applies to both construction and destruction.
So, in your case, the most economical way to avoid an unresolved problem with std::is_nothrow_move_constructible is to use a new placement, avoiding the problem with std::bad_alloc (mentioned in Chris Beck's comment), and similarly, use the T descriptor for the wrapper 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_; };
source share