在标准文本中, 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 !!!
(示例是关于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
示例略有不同,但不是那些相同的东西?何时以及如何使用initializer_list
- 构造函数进行重载解析?或者这里有不同的问题吗?
两种情况下如何确定重载?如果两者都正确,我在这里想念什么?
在 Keric的上编辑/澄清评论:我的感觉是,这两个例子相互矛盾:
const char*
转换为string
,与提供的initializer_list<int>
不匹配,因此提供的“正常”const string&
- c '使用了。{double, double}
- c'tor可用并因此被选中时,Scott的示例用intializer_list<int>
初始化,因为他认为该列表是首选。因此,当以这种方式初始化时,也永远不会选择(double, double)
- c'tor。当然,Std总是对的,但也许我错误地应用了这个例子。标准示例中有&
,我认为这与我的问题无关,但也许我错了。
编辑-2 :我收到了斯科特本人的一封邮件,其中有late change in the Standard未合并到幻灯片中。
答案 0 :(得分:5)
根据N3291,2011年4月5日的工作草案,初始化程序列表有一些变化,因此Scott Meyer的幻灯片可能来自旧数据。
根据第13.3.1.7节(如此接近1337):
- 最初,候选函数是类T的初始化列表构造函数(8.5.4),参数列表由初始化列表作为单个参数组成
- 如果找不到可行的初始化列表构造函数,则再次执行重载解析,其中候选函数是类T的所有构造函数,参数列表由初始化列表的元素组成。
所以它确实更喜欢initailizer列表。但是如果初始化列表不匹配,那么它将检查常规构造函数以查看它们是否匹配。
接着说,如果初始化列表为空,则使用默认构造函数。