为什么`vector <int> v {{5,6}};`工作?我以为只允许一对{}被允许?

Aar*_*aid 10 initializer-list c++11

给定一个A带有两个构造函数的类,分别取initializer_list<int>initializer_list<initializer_list<int>>

A v{5,6};
Run Code Online (Sandbox Code Playgroud)

叫前者,和

A v{{5,6}};
Run Code Online (Sandbox Code Playgroud)

按预期调用后者.(clang3.3,显然gcc表现不同,请看答案.标准需要什么?)

但是如果我删除第二个构造函数,那么A v{{5,6}};仍然编译并使用第一个构造函数.我没想到这一点.我认为这A v{5,6}将是访问构造函数的唯一方法initializer_list<int>.

(我发现这一点的同时与玩弄std::vector这个问题,我问在Reddit上,但我创建了自己的A级,以确保它不只是一个对接口的怪癖std::vector.)

小智 3

我认为这个答案可能是相关的

\n\n
\n

是的,根据 \xc2\xa713.3.1.7 通过列表初始化初始化\n,此行为是有意的

\n\n
\n

当非聚合类类型 T 的对象被列表初始化时 (8.5.4),重载决策分两个阶段选择构造函数:

\n\n

\xe2\x80\x94 最初,候选函数是类 T 的初始值设定项列表构造函数 (8.5.4),参数列表由初始值设定项列表作为单个参数组成。

\n\n

\xe2\x80\x94 如果没有找到可行的初始化器列表构造函数,则再次执行重载决策,其中候选函数都是类 T 的构造函数,参数列表由初始化器列表的元素组成。

\n
\n
\n\n

我试过gcc你的例子。我收到此错误:

\n\n
error: call of overloaded \'A(<brace-enclosed initializer list>)\' is ambiguous\n
Run Code Online (Sandbox Code Playgroud)\n\n

gcc如果我使用三套支架,就不再抱怨了。IE:

\n\n
error: call of overloaded \'A(<brace-enclosed initializer list>)\' is ambiguous\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

为了镜像向量的构造函数,以下是我的结果:

\n\n
#include <iostream>\n#include <vector>\n#include <initializer_list>\n\nstruct A {\n    A (std::initializer_list<int> il) { \n        std::cout << "First." << std::endl;\n    }\n    explicit A (std::size_t n) {\n        std::cout << "Second." << std::endl;\n    }\n    A (std::size_t n, const int& val) {\n        std::cout << "Third." << std::endl;\n    }\n    A (const A& x) {\n        std::cout << "Fourth." << std::endl;\n    }\n};\n\nint main()\n{\n    A a{0};\n    A a2{{0}};\n    A a3{1,2,3,4};\n    A a4{{1,2,3,4}};\n    A a5({1,2,3,4});\n    A a6(0);\n    A a7(0, 1);\n    A a8{0, 1};\n}\n\nmain.cpp:23:10: warning: braces around scalar initializer\n\n    A a2{{0}};\n\n         ^~~\n\n1 warning generated.\n\nFirst.\nFirst.\nFirst.\nFirst.\nFirst.\nSecond.\nThird.\nFirst.\n
Run Code Online (Sandbox Code Playgroud)\n