C++变体:为什么转换构造函数需要大小.(类型)为非零
C++ Variant: Why does Converting constructor require sizeof...(Types) to be nonzero
这个问题是关于:template<class...Types> class variant
:
根据 variant.variant/3,在没有模板参数的情况下实例化variant
的程序格式不正确。
到目前为止,如此清晰。现在我有一个关于转换构造函数的问题(template<class T> constexpr variant(T&& t) noexcept(see below)
):
variant.variant/variant.ctor-16.1 表示转换构造函数不得参与重载解析,除非:
大小...(类型)为非零
(...以及其他一些我现在不关心的要求)。
我的问题是,当没有模板参数的variant
已经使我的程序格式不正确时,为什么还要关心我的转换构造函数是否参与重载解析?
看看 MSVC 和 libstdc++ -variant
的实现,他们实际上对转换构造函数的声明有enable_if_t<sizeof...(_Types) != 0>
。为什么?
子句"sizeof...(类型)为非零">作为论文的一部分添加到[variant.ctor]
:对类模板参数推导的一些改进集成到标准库中,以允许variant
支持。
相关摘录:
启用变体支持
以下代码编译失败
variant<int, double> v1(3); variant v2 = v1; // Ill-formed! <--THIS
由于这种自然代码很有用,并且它的失败令人困惑,我们建议支持它。事实上,在采用 p0510r0 禁止
variant<>
之前,上面的代码按预期工作,因为variant<>
发生在过载集中的一些演绎指南中。由于不清楚在采用 p0510r0 时是否考虑了构造函数模板参数推导,因此我们想考虑允许variant<>
在这种情况下不产生硬错误。措辞(着重号另加)
更改§23.7.3.1p16[variant.ctor]
如下:
备注:此函数不应参与重载解析,除非sizeof...(Types)
为非零,除非is_same_v<decay_t<T>, variant>
false
,除非decay_t<T>
既不是in_place_type_t
的特化也不是in_place_index_t
的特化,除非is_constructible_v<Tj, T>
是true
的,除非表达式 FUN(std::forward(t))(FUN是上述虚函数的集合)格式良好。
因此,std::variant v2 = v1;
未考虑添加子句的编译器版本中失败(如GCC 7.1。请参阅DEMO),但在更高版本(从 GCC 7.2 开始)上成功。请参阅演示)。
- 访问者访问变体并返回不同类型时出错
- 我应该使用什么来代替void作为变体中的替代类型之一
- 当无法使用模板和宏时,生成类型变体C++代码的最简单方法是什么?
- 如何使用可变参数模板强制转换每个变体类型
- 类型双关主题的变体:就地琐碎构造
- C++ 相同基础类型的变体
- C++:是否可以编写一个函数,将不同类型的元素附加到变体数组中?
- 具有独特类型的变体
- 使用自定义访问者时具有自定义类型的提升变体失败(源自 boost::static_visitor)
- 在 std::visit 中跳过变体类型的一些重载组合的方法是什么?
- 如何多态地使用替代类型的 std::变体
- c++17通过生成预先声明的类型列表的笛卡尔乘积来生成std::变体
- C++ 相互递归的变体类型(再次)
- 我可以使用特征指定变体的类型列表吗?
- 创建提升 - 通用 C 结构的变体类型
- C++ 在地图中存储变体类型
- 如果变体类型之一,如何启用模板函数?
- STD ::变体和不完整类型:它如何工作
- 如何使用%类型指令使用std ::变体类型
- 具有不同返回类型的变体访客