【问题标题】:About how the alternative is selected on variant construction with a single argument?关于如何在具有单个参数的变体构造中选择替代方案?
【发布时间】:2020-04-28 09:16:24
【问题描述】:

一边阅读标准构造函数[variant.ctor]的定义:

template<class T> constexpr variant(T&& t) noexcept(see below);

我遇到了一个模糊的限制:

Tj 是一个类型,确定如下:为每个替代类型Ti 构建一个假想函数Ti Ti x[] = {std​::​forward&lt;T&gt;(t)};对于某些发明的变量 x 是格式良好的 ...他为表达式 FUN(std​::​forward&lt;T&gt;(​t)) 的重载解析选择的重载 FUN(Tj) 定义了替代 Tj ,这是构造后包含的值的类型。

我想了解这个限制背后的意图是什么:

对于哪个Ti x[] = {std​::​forward&lt;T&gt;(t)};格式正确

如果没有这个限制,重载解析将消除所有无法通过复制初始化初始化参数的重载。

据我所知,Ti x[] = {std::forward&lt;T&gt;(t)} 应该落在[dcl.init.aggr]/2

否则,元素从相应的初始化子句复制初始化,或者使用相应的指定初始化子句的大括号或相等初始化子初始化。如果该初始值设定项的形式为 assignment-expression 或 = assignment-expression,并且需要一个窄化转换 ([dcl.init.list]) 来转换该表达式,则该程序是非良构的

所以我看到这个限制从重载的虚函数集中删除了那些在调用时会涉及缩小转换的函数。但也许还有更多?我错了吗?为什么在限制中进行数组初始化,为什么不Ti x = {std::forward&lt;T&gt;(t)}? “Ti x[] = {std​::​forward&lt;T&gt;(t)}; 格式正确”背后的意图是什么?

【问题讨论】:

  • 好吧,如果它是Ti x = {std::forward&lt;T&gt;(t)},那么即使初始化列表不是参数,它也会允许初始化列表构造函数。通过使其成为一个数组,它永远不会允许这种情况。但我不知道这是否真的是决定的一个因素

标签: c++ initialization language-lawyer variant


【解决方案1】:

此措辞由P0608R3 A sane variant converting constructor 添加。论文在Proposed resolution部分很好地总结了变化:

本文提出约束variant转换构造函数 和转换赋值运算符以防止缩小 转换和转换为bool。本节说明了什么 正是这种变化带来了。

因此,此更改的唯一目的是防止缩小转化率。

为什么要使用数组? Wording 部分中的起草说明回答了您的问题:

[ 草稿注释:以上使用Ti x[] = {std::forward&lt;T&gt;(t)};而不是 Ti {std::forward&lt;T&gt;(t)} 测试是否 从TTi 的转换序列包含一个缩窄 转换,因为是否 Ti {std::forward&lt;T&gt;(t)} 格式正确 取决于Ti 是否有initializer_list 构造函数或 Ti 是否是一个聚合。这是一个 示例:https://godbolt.org/z/Ck5w-L– 尾注]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-17
    • 1970-01-01
    • 2018-07-24
    • 1970-01-01
    • 2021-11-17
    • 1970-01-01
    • 2015-03-20
    • 2019-06-04
    相关资源
    最近更新 更多