我正在学习如何使用条件noexcept
并遇到这个问题。假设我有一个班级:
template<typename T>
class Wrapper {
public:
Wrapper(T&& value) noexcept(/* ??? */)
: value_(std::move(value))
{}
private:
T value_;
};
对于/* ??? */
部分,我认为我们可以使用noexcept(T(std::move(value)))
或std::is_nothrow_move_constructible<T>::value
,直到我偶然发现this。
所以如果我使用noexcept(noexcept(T(std::move(value))))
,严格来说我说“这个构造函数是noexcept
iff构建并破坏 T
是{{1} }}“?
虽然扔掉的破坏者应该被点燃并烧毁。
答案 0 :(得分:6)
好问题,另见this language defect discussion。从它的名字可以清楚地看出std::is_nothrow_move_constructible<T>::value
应该只与rvalue的构造结构有关(但实际上也可能与破坏有关),而noexcept(T(std::move(value)))
总是与两者有关建设和破坏。
因此,在您的情况下,避免未解决的std::is_nothrow_move_constructible
特征问题的最省钱方法是使用新的位置,避免std::bad_alloc
的问题(在Chris Beck的评论中提到),并且,类似地,使用T
的析构函数作为包装器的析构函数。
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_;
};