我最近关注了Reddit上的一次讨论,涉及到不同编译器中
该声明的意思是,这使任何变量都无价值,并且阅读docu应该做到以下几点:
首先,销毁当前包含的值(如果有)。然后,直接使用参数
我不理解的是:为什么它被说明为“可能”?如果整个操作抛出异常,保持旧状态是否合法?因为这就是GCC所做的。
因此,基本上它创建了一个临时变量,如果成功,则将其复制/移动到实际位置。
我认为这违反了文档中所述的“首先,销毁当前包含的值”。按照标准,然后在
我确实知道条件
响应标准引用的编辑:
std::visit
优化的比较。我注意到以下内容:https://godbolt.org/z/D2Q5ED
GCC9和Clang9(我猜它们共享同一个stdlib)在所有类型都满足某些条件时不会生成用于检查并抛出无值异常的代码。这导致更好的代码生成,因此我提出了一个MSVC STL问题,并得到了以下代码:template <class T>
struct valueless_hack {
struct tag {};
operator T() const { throw tag{}; }
};
template<class First, class... Rest>
void make_valueless(std::variant<First, Rest...>& v) {
try { v.emplace<0>(valueless_hack<First>()); }
catch(typename valueless_hack<First>::tag const&) {}
}
该声明的意思是,这使任何变量都无价值,并且阅读docu应该做到以下几点:
首先,销毁当前包含的值(如果有)。然后,直接使用参数
std::forward<Args>(args)....
构造类型T_I
的值。如果抛出异常,则*this
可能会因异常而变得没有价值。我不理解的是:为什么它被说明为“可能”?如果整个操作抛出异常,保持旧状态是否合法?因为这就是GCC所做的。
// For suitably-small, trivially copyable types we can create temporaries
// on the stack and then memcpy them into place.
template<typename _Tp>
struct _Never_valueless_alt
: __and_<bool_constant<sizeof(_Tp) <= 256>, is_trivially_copyable<_Tp>>
{ };
之后它(有条件地)执行类似以下的操作:
T tmp = forward(args...);
reset();
construct(tmp);
// Or
variant tmp(inplace_index<I>, forward(args...));
*this = move(tmp);
因此,基本上它创建了一个临时变量,如果成功,则将其复制/移动到实际位置。
我认为这违反了文档中所述的“首先,销毁当前包含的值”。按照标准,然后在
v.emplace(...)
之后,变量中的当前值始终被销毁,新类型是设置的类型或无值的。我确实知道条件
is_trivially_copyable
排除了所有具有可观察析构函数的类型。因此,这也可以理解为:“好像变量重新初始化为旧值”之类的东西。但是,变量的状态是一种可观察的效果。因此,标准确实允许emplace
不更改当前值吗?响应标准引用的编辑:
然后使用参数
std::forward<Args>(args)...
直接非列表初始化类型TI的值来初始化包含的值。
T tmp {std::forward<Args>(args)...}; this->value = std::move(tmp);
真的算作上述内容的有效实现吗?这就是“好像”所指的吗?