详题:为什么std:variant
的operator=(T&& t)
的noexcept规范不依赖于内部类型的析构函数的noexcept规范?
我可以在cppreference 上看到
template <class T> variant& operator=(T&& t) noexcept(/* see below */);
是
noexcept(std::is_nothrow_assignable_v<T_j&, T> &&
std::is_nothrow_constructible_v<T_j, T>)
所以这编译:
struct FooThrow {
~FooThrow() noexcept(false) {throw;}
};
static_assert(std::is_nothrow_assignable_v<std::variant<FooThrow, int>, int>);
但它调用FooThrow
的析构函数是noexcept(false)
:
std::variant<FooThrow, int> x;
x = 3; // throws
好像不对。我错过了什么吗?
通常,标准库类型对具有抛出析构函数的类型不友好。或者具体来说,当析构函数实际发出异常时。关于它有一个一般规则([res.on.functions])
在某些情况下(替换函数、处理函数、用于实例化标准库模板组件的类型操作),C++ 标准库依赖于由 C++ 程序提供的组件。如果这些组件不满足它们的要求,本国际标准不对其实施提出要求。
特别是,在以下情况下效果是不确定的:
...
- 如果任何替换函数或处理函数或析构函数操作通过异常退出,除非在适用的必需行为:段落中特别允许。
由于variant::operator=
没有关于抛出析构函数的特殊声明,让这些析构函数实际抛出是 UB。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句