【发布时间】:2011-07-19 08:51:39
【问题描述】:
在Standard-Text中有一个例子在8.5.4 (3) List-initialization [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-constructors 解决重载问题?还是这里有不同的问题?
这两种情况下的重载是如何决定的?如果两者都是正确的,我在这里错过了什么?
编辑/澄清 Keric 的评论:我的感觉是,这两个例子相互矛盾:
- Std 给出了一个示例,其中将
const char*转换为string,这与提供的initializer_list<int>不匹配,因此使用提供的“正常”const string&-c'tor。 - Scott 的示例在
intializer_list<int>-c'tor 可用并因此选择时使用{double, double}进行初始化,因为他认为该列表是首选。因此,以这种方式初始化时,永远不会选择还提供的(double, double)-c'tor。
当然,Std 总是正确的,但也许我错误地应用了这个例子。 Std 示例中有&,我认为这与我的问题无关,但也许我错了。
Scott 的幻灯片是最新的,我看不到标准中的相关部分已经改变到这方面(尽管很难将所有内容都纳入范围,因为它有点“广泛传播”:-)
Edit-2:我收到了 Scott 本人发来的邮件,说有一个 late change in the Standard 没有被合并到幻灯片中。
【问题讨论】:
-
如果标准是最新的标准,那么标准是正确的。某人(无论多么有影响力)在幻灯片上放什么并不重要。如果标准实际上在语言本身中说(示例是非规范性的),那么它应该是这样工作的。
-
我不完全确定您的问题是什么,或者您发现示例的哪一部分不清楚或矛盾。你能澄清一下吗?旧的 N3242 说 (8.5.4(2)):“在列表初始化中,初始化列表构造函数比其他构造函数更受青睐”。我认为这很清楚,不是吗? (另见 13.3.3.1.5 转换为初始化列表。)
-
可以将
const char[]转换为std::initializer_list<double>(真的是doubles 的数组)吗?我认为问题在于你的构造函数参数仍然需要匹配,不管有没有隐式转换。 -
令人惊讶的是,gcc 4.5.1。第二次初始化失败:ideone.com/Szbts
标签: c++11 overloading initializer-list