C++ 0x:重载决议

tow*_*owi 3 overloading initializer-list c++11

在标准文本中,8.5.4(3)列表初始化[dcl.init.list]中有一个例子

struct S {
    S(std::initializer_list<double>);  // #1
    S(const std::string&);             // #2
};
const S& r1 = { 1, 2, 3.0 };  // OK: invoke #1
const S& r2 { "Spinach" };    // OK: invoke #2 !!!
Run Code Online (Sandbox Code Playgroud)

(示例是关于ref-to-temp,但我在这里指的是重载决策).

Scott Meyers在他的演讲/幻灯片中讲述了一个不同的故事:

std :: initializer_list参数始终优先于其他类型:

class Widget {
public:
    Widget(double value, double uncertainty);           // #1
    Widget(std::initializer_list<std::string> values);  // #2
};
double d1, d2;
Widget w1 { d1, d2 }; // tries to call #2; fails because
                      // no double ? string conversion
Run Code Online (Sandbox Code Playgroud)

这些例子略有不同,但不是那些相同的东西?何时以及如何使用initializer_list-constructors进行重载解析?或者这里有不同的问题吗?

两种情况下如何确定超载?如果两者都正确,我在这里想念什么?

编辑/澄清Keric的评论:我的感觉IST,这两个例子互相矛盾:

  • Std给出了一个例子,其中a const char*被转换为a string,它与提供的不匹配initializer_list<int>,因此使用提供的"normal" const string&-c'tor.
  • 斯科特的例子初始化{double, double}时,intializer_list<int>-c'tor可用并因此被选中,因为他认为该列表是首选.因此,(double, double)当以这种方式初始化时,也不会选择提供的-c'tor.

当然,Std总是正确的,但也许我错误地应用了这个例子.Std的例子中有&我不认为与我的问题有关,但也许我错了.

斯科特的幻灯片是最新的,我看不出标准中的相关部分已经改变到那个方面(尽管,很难将所有内容都纳入范围,因为它有点"广泛传播":-)

编辑-2:我收到了斯科特本人的一封邮件,标准中有一个晚期的变化没有被纳入幻灯片.

Nic*_*las 5

根据2011年4月5日的工作草案N3291,初始化程序列表发生了一些变化,因此Scott Meyer的幻灯片可能来自旧数据.

根据第13.3.1.7节(如此接近1337):

  • 最初,候选函数是类T的初始化列表构造函数(8.5.4),参数列表由初始化列表作为单个参数组成
  • 如果找不到可行的初始化列表构造函数,则再次执行重载解析,其中候选函数是类T的所有构造函数,参数列表由初始化列表的元素组成.

所以它确实更喜欢initailizer列表.但是如果初始化列表不匹配,那么它将检查常规构造函数以查看它们是否匹配.

接着说,如果初始化列表为空,则使用默认构造函数.