最近,我关注了Reddit的一次讨论,该讨论导致在编译器之间对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&) {}
}这种说法是,这使得任何变体都是毫无价值的,并且阅读多古它应该:
首先,销毁当前包含的值(如果有的话)。然后直接初始化包含的值,就好像用参数
T_I构造std::forward<Args>(args)....类型的值一样,如果抛出异常,*this可能变成valueless_by_exception。
我不明白的是:为什么会写成“可以”呢?如果整个行动失败的话,留在原来的状态合法吗?因为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(...)之后,变体中的当前值总是被销毁,新类型要么是set类型,要么是无值类型。
我确实知道,条件is_trivially_copyable排除了所有具有可观测析构函数的类型。因此,这也可以是:"as-if变量用旧值重新初始化“左右。但是变体的状态是一个可以观察到的效果。那么,标准是否允许emplace不更改当前值?
根据标准报价编辑:
然后初始化包含的值,就好像直接-非列表-使用参数
std::forward<Args>(args)...初始化TI类型的值一样。
T tmp {std::forward<Args>(args)...}; this->value = std::move(tmp);真的是上述功能的有效实现吗?这就是“好像”的意思吗?
发布于 2019-11-13 10:45:22
我认为标准的重要部分是:
来自https://timsong-cpp.github.io/cppwp/n4659/variant.mod#12
23.7.3.4 Modifiers (...) 模板variant_alternative_t>&嵌入(Args&&.( args); (...)如果在初始化包含的值期间抛出异常,则变体可能不包含值。
上面写着“可能”而不是“必须”。我希望这是有意的,以便允许像gcc那样的实现。
正如您自己提到的,只有当所有备选方案的析构函数都是微不足道的,因此无法观察到,因为需要销毁以前的值时,这才有可能实现。
后续问题:
Then initializes the contained value as if direct-non-list-initializing a value of type TI with the arguments std::forward<Args>(args)....tmp {std::转发(Args).};this->value = std::move(tmp);真的算作上述实现的有效实现吗?这就是“好像”的意思吗?
是的,因为对于属于微不足道的可复制的类型,没有办法检测到差异,因此实现的行为就像初始化了所描述的值一样。如果该类型不具有可复制性,则此操作将不起作用。
https://stackoverflow.com/questions/58834389
复制相似问题