在 C++ 标准 §13.3.1.7 [over.match.list] 中,声明如下:
在复制列表初始化中,如果
explicit
选择了构造函数,则初始化格式错误。
这就是为什么我们不能这样做的原因,例如,这样的事情:
struct foo {
// explicit because it can be called with one argument
explicit foo(std::string s, int x = 0);
private:
// ...
};
void f(foo x);
f({ "answer", 42 });
(请注意,这里发生的不是转换,即使构造函数是“隐式的”也不会是转换。这是foo
直接使用其构造函数初始化对象。除了 之外std::string
,这里没有转换。)
这对我来说似乎很好。隐式转换绝不会咬我。
如果{ "answer", 42 }
可以初始化其他东西,编译器就不会背叛我做错事:
struct bar {
// explicit because it can be called with one argument
explicit bar(std::string s, int x = 0);
private:
// ...
};
void f(foo x);
void f(bar x);
f({ "answer", 42 }); // error: ambiguous call
没有问题:调用不明确,代码无法编译,我必须明确选择重载。
f(bar { "answer", 42 }); // ok
由于明确规定了禁令,我觉得我在这里遗漏了一些东西。据我所知,列表初始化选择显式构造函数对我来说似乎不是问题:通过使用列表初始化语法,程序员已经表达了进行某种“转换”的愿望。
会出什么问题?我错过了什么?