除了(或甚至代替)std::variant
自由函数之外,使get< T >()
类的一部分成为显式转换(替代)运算符重载的缺点是什么(p.568 draft)?
template<class... Types>
class variant
{
template<class T>
explicit operator const T& () const&;
template<class T>
explicit operator T& () &;
template<class T>
explicit operator const T&& () const &&;
template<class T>
explicit operator T&& () &&;
};
在某些情况下它是不安全的吗?为什么我们需要免费的get()
函数(即&#34;类型&#34;版本,而不是&#34;索引&#34;一个),当variant公开一个值语义时(引用草案):< / p>
变体对象保存并管理值的生命周期。
是否足以使变种明确地转换为替代品,但仍然可以从替代品中隐式构建?
我知道,界面的一致性是好事(我记得我们需要get< I >()
和get< T >()
),但我认为仅仅通过转换为更自然的方式来包含替代值它,而不是将一些函数专门化应用于变体实例。
答案 0 :(得分:3)
我可以想到一些缺点:
std::variant
可以包含 cv void
,但转换函数会返回 cv void&
和 cv void&&
将是非法的,并且永远不会调用 cv void
的转换函数( [class.conv.fct] / 1); std::variant
可以保存一个也可以从中构造的类型,例如:std::variant<std::monostate, std::any> v; std::any a{v};
- 在这种情况下会发生什么?此外,目前可以使用返回T
的函数,将其转换为返回std::variant<T, U>
的函数,并期望编译器检测需要更改代码的所有情况;转换函数为T
任何代码复制或绑定对T
的引用的情况都会导致错误:
int f();
int i{f()}; // OK
// f() changes to:
std::variant<int, std::string> f();
int i{f()}; // can now throw std::bad_variant_access
答案 1 :(得分:1)
1)如果std::variant
只有一个案例,我认为有一个案例是无争议的。 (这可能发生在通用代码中。)然后变量应该(隐式地,IMO)可转换为该单一类型。
std::variant<double> v(5.3);
...
double d; d = v; // should be ok
2)对于其他非退化情况,我认为它应该可以转换(显式),就像std::get
那样。
我只会针对原始 variant
的情况(而不是任意类型)执行此操作。
std::variant<double, int> v(5.3);
...
double d{v}; // should be ok, but can throw
我不认为因void
案例而没有这个功能的借口是好的。
在最坏的情况下,void
是问题,而不是variant
。
void
个案件应由monostate
处理(或将来由“常规void
”处理。
总而言之,我支持你的想法,除了我会对转换运算符施加限制。
另外,我会返回一个副本而不是一个引用(绝对不是非常量引用)。
原因是,通过引用,可以将变体内容置于无效状态(如原始联合所发生的那样),或者如果变体稍后更改,则引用本身可能处于无效状态。
[编辑:我把它拿回去,引用一直无效,这没关系,例如,如果你引用了一个向量的元素,并且稍后调整了向量。]
template<class... Types>
class variant
{
template<class T>
explicit operator T&() const{return std::get<T>(*this);}
...
};
template<class T>
class variant
{
/*implicit*/ operator T&() const{return std::get<T>(*this);}
...
};
由于缺少该功能,一些临时解决方法
一个。派生自std::variant
并添加这些功能。从变体中衍生或聚集似乎是一种常见的模式。
湾变体案例的重载函数,因此它可以直接使用变体并立即调用std::get<type>(...)
上的原始函数。
答案 2 :(得分:0)
我不提出建议的主要原因如下:
explicit operator bool()
(has_value()
或不?)但鉴于正确的论据,这肯定会在未来的修订中改变。