在 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 });
(Note that what happens here is not a conversion, and it would not be one even if the constructor was "implicit". This is initialization of a foo
object using its constructor directly. Other than the std::string
, there is no conversion here.)
这对我来说似乎完全没问题。隐式转换不可能让我烦恼。
If { "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
由于明确规定了禁令,我感觉我在这里遗漏了一些东西。据我所知,列表初始化选择显式构造函数对我来说似乎不是问题:通过使用列表初始化语法,程序员已经表达了进行某种“转换”的愿望。
可能会出什么问题?我缺少什么?