直接列表初始化编译成功,但是正常直接初始化失败,为什么? [英] Direct list initialization compiles successfully, but normal direct initialization fails, why?

查看:28
本文介绍了直接列表初始化编译成功,但是正常直接初始化失败,为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如这样的代码:

struct A { A(int); };
struct B { B(A);   };

int main()
{
    B b{{0}}; // OK
    B c({0}); // error
}

错误信息是:

f.cc: In function 'int main()':
f.cc:7:9: error: call of overloaded 'B(<brace-enclosed initializer list>)' is ambiguous
  B c({0}); // error

         ^
f.cc:7:9: note: candidates are:
f.cc:2:12: note: B::B(A)
 struct B { B(A);   };
        ^
f.cc:2:8: note: constexpr B::B(const B&)
 struct B { B(A);   };
        ^
f.cc:2:8: note: constexpr B::B(B&&)

推荐答案

从最新的官方标准C++14开始,你的第一次初始化是没有歧义的.[over.match.list]:

As of the latest official standard, C++14, your first initialization is not ambiguous. [over.match.list]:

由于不存在初始化列表构造函数,我们进入第二阶段".现在考虑 [over.best.ics]/4:

As no initializer-list constructors exist, we enter the "second phase". And now consider [over.best.ics]/4:

我们的元素是 {0}.因此这不允许(用户定义的)转换 {0} -> A 用于复制构造函数.显然,如果我们不在 [over.match.list] 的第二阶段,这不适用,因此对于您使用 B c({0}) 的示例,不会发生列表初始化对于 c 并考虑两个构造函数.

Our element is {0}. Hence this disallows the (user-defined) conversion {0} -> A for the copy constructor. Clearly, this doesn't apply if we aren't in the second phase of [over.match.list], so for your example with B c({0}), no list-initialization occurs for c and both constructors are considered.

第一个初始化当前与第二个初始化一样模棱两可.编译器根本没有实现 CWG #1467 - 它的决议删除了上面引用的要点 (4.5).
请参阅 #2076,选择还原更改:

The first initialization is currently just as ambiguous as the second one. Compilers simply haven't implemented CWG #1467 yet - its resolution removed bullet point (4.5), quoted above.
See #2076, which opts to revert the change:

issue 1467的决议一些似是而非的结构格式不正确.例如,

The resolution of issue 1467 made some plausible constructs ill-formed. For example,

struct A { A(int); };
struct B { B(A); };
B b{{0}};

这现在是模棱两可的,因为文本不允许用户定义B 的复制和移动构造函数的转换已从13.3.3.1 [over.best.ics] 第 4 段.

This is now ambiguous, because the text disallowing user-defined conversions for B's copy and move constructors was removed from 13.3.3.1 [over.best.ics] paragraph 4.

文本"是前面提到的要点.Richard Smith 提出以下措辞:

"The text" is the aforementioned bullet point. Richard Smith proposes the following wording:

对于非类类型,我们允许从单项列表初始化仅当列表中的元素本身不是 a 时才执行复制列表(13.3.3.1.5 [over.ics.list] 项目符号 9.1).类似的规则这种情况是在 13.3.3.1 [over.best.ics] 中添加回项目符号第 4 段,但仅限于初始化程序本身是初始化列表:

For non-class types, we allow initialization from a single-item list to perform a copy only if the element within the list is not itself a list (13.3.3.1.5 [over.ics.list] bullet 9.1). The analogous rule for this case would be to add back the bullet in 13.3.3.1 [over.best.ics] paragraph 4, but only in the case where the initializer is itself an initializer list:

        第二期13.3.1.7 [over.match.list] 当初始化列表恰好有一个         元素时本身是一个初始化列表,其中目标是第一个参数构造函数
        属于X类,转换为到 X 或引用(可能是 cv 限定的)X,

        the second phase of 13.3.1.7 [over.match.list] when the initializer list has exactly one         element that is itself an initializer list, where the target is the first parameter of a constructor
        of class X, and the conversion is to X or reference to (possibly cv-qualified) X,

由于初始化器 {0} 本身就是一个初始化器列表,因此该要点将使您的第一次初始化再次形成良好的格式.

As the initializer {0} is itself an initializer list, that bullet point would make your first initialization well-formed again.

这篇关于直接列表初始化编译成功,但是正常直接初始化失败,为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆