C++11 统一初始化:初始化列表和多参数构造函数之间的歧义?

Tim*_*sky 7 c++ c++11

目前正试图围绕 C++11 的统一初始化进行思考。我遇到了这个模棱两可的情况:考虑一个类,它可以由一个双参数构造函数或一个任意长度的初始化列表构造:

class Foo {
  public:
    Foo(int a, int b) {
      std::cout << "constructor 1" << std::endl;
    }
    Foo(std::initializer_list<int>) {
      std::cout << "constructor 2" << std::endl;
    }
};
Run Code Online (Sandbox Code Playgroud)

遵循统一的初始化约定,我希望以下内容起作用:

Foo a (1, 2)印刷品constructor 1(废话)

Foo b {1, 2} 印刷 constructor 1

Foo c = {1, 2} 印刷 constructor 2

但是,编译器似乎将其解释Foo b {1, 2}为列表初始化,并调用构造函数 2。()当存在初始化列表构造函数时,语法是否是强制编译器考虑其他类型构造函数的唯一方法?

And*_* DM 1

\n

编译器似乎将 Foo b {1, 2} 解释为列表初始化,并调用构造函数 2。() 语法是强制编译器在初始化列表构造函数\n时考虑其他类型构造函数的唯一方法吗?存在?

\n
\n

标准草案的引文很好地解释了这一点:

\n

9.4.5.2 [dcl.init.list](强调我的):

\n
\n

如果构造函数的第一个参数的类型为 std\xe2\x80\x8b::\xe2\x80\x8binitializer_\xc2\xadlist 或对 cv\nstd\xe2\x80\x8b::\ 的引用,则该构造函数是初始值设定项列表构造函数xe2\x80\x8binitializer_\xc2\xadlist 对于某些类型 E,并且要么没有\n其他参数,要么所有其他参数都有默认参数\n([dcl.fct.default])。

\n
\n
\n

[注 2:初始化列表构造函数比列表初始化中的其他构造函数更受青睐([over.match.list])。将初始值设定项列表作为参数传递给\n类 C 的构造函数模板 C(T) 不会\n创建初始值设定项列表构造函数,因为初始值设定项列表\n参数会导致相应的参数成为非推导\n上下文 ( [临时扣除呼叫])。\xe2\x80\x94 尾注]

\n
\n

12.4.2.8 [over.match.list]

\n
\n

当非聚合类类型 T 的对象被列表初始化时,\n[dcl.init.list] 指定根据本子条款中的规则\n执行重载解析,或者根据 [over .ics.list],重载\n解析分两个阶段选择构造函数:

\n
\n
    \n
  • \n
    \n

    如果初始值设定项列表不为空或 T 没有默认构造函数,则首先执行重载解析,其中候选函数\n是类 T 的初始值设定项列表构造函数([dcl.init.list]) 和参数列表由作为单个参数的初始值设定项列表组成。

    \n
    \n
  • \n
  • \n
    \n

    否则,或者如果找不到可行的初始值设定项列表构造函数,则再次执行重载解析,其中候选函数是类 T 的所有构造函数,参数列表由初始值设定项列表的元素组成。

    \n
    \n
  • \n
\n