C++ 直接列表初始化成功编译,但正常的直接初始化失败,原因是什么?
例如,代码如下所示:C++ 直接列表初始化成功编译,但正常的直接初始化失败,原因是什么?,c++,initialization,overload-resolution,C++,Initialization,Overload Resolution,例如,代码如下所示: 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
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&&)
f.cc:在函数“int main()”中:
f、 cc:7:9:错误:重载的“B()”的调用不明确
bc({0});//错误
^
f、 抄送:7:9:注:候选人为:
f、 抄送:2:12:注:B::B(A)
结构B{B(A);};
^
f、 抄送:2:8:注意:constexpr B::B(const B&)
结构B{B(A);};
^
f、 抄送:2:8:注:constexpr B::B(B&&)
根据最新的官方标准C++14,您的第一次初始化并不含糊。[over.match.list]:
由于不存在初始值设定项列表构造函数,我们进入“第二阶段”。现在考虑[Bo.Best.ICS] / 4:
我们的元素是{0}
。因此这不允许复制构造函数的(用户定义的)转换{0}
->A
。显然,如果我们不在[over.match.list]的第二阶段,这不适用,因此对于您的bc({0})
示例,c
不会发生列表初始化,并且会考虑这两个构造函数
CWG第1467期 第一次初始化与第二次初始化一样不明确。编译器还没有实现CWG——它的解决方案删除了上面引用的要点(4.5)。
请参阅,哪些选项选择恢复更改: 这项决议提出了一些似是而非的构想 格式不正确。比如说,
struct A { A(int); };
struct B { B(A); };
B b{{0}};
这现在是不明确的,因为文本不允许用户定义
已从中删除B
的复制和移动构造函数的转换
13.3.3.1[超过最佳ics]第4段
“文本”是上述要点。理查德·史密斯提出以下措辞:
对于非类类型,我们允许从单个项列表进行初始化
仅当列表中的元素本身不是
清单(13.3.3.1.5[超过ics清单]项目符号9.1)的类似规则
本例将在第13.3.3.1节[over.best.ics]中添加该项目符号
第4段,但仅在初始值设定项本身为
初始值设定项列表:
第二阶段
13.3.1.7[超过匹配列表]当初始值设定项列表只有一个元素
它本身是一个初始值设定项列表,其中目标是
构造函数类
X
,并且转换为
至X
或参考(可能符合cv条件)X
由于初始值设定项
{0}
本身就是一个初始值设定项列表,因此该要点将使您的第一次初始化再次格式良好。是的,它应该是公共的。我已经改变了,谢谢!令人惊讶的是,这失败了,即使我删除了B的复制和移动构造函数:编译错误消息相当令人费解,它与已删除的函数是不明确的。@ChrisBeck已删除的函数参与重载解析,因此删除它们没有什么区别B({{{0}}});我不知道为什么。也许是伏都教?我认为构造{}
的大括号形式从不采用初始值设定项列表,但paren版本()
总是采用,即使没有初始值设定项列表构造函数。这个答案提供了一些信息,但不是一个确定的答案。