In the C++ standard, §13.3.1.7 [over.match.list], the following is stated:
In copy-list-initialization, if an explicit
constructor is chosen, the initialization is ill-formed.
This is the reason why we can't do, for example, something like this:
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.)
This seems perfectly fine to me. There's no way that an implicit conversion will bite me.
If { "answer", 42 }
can initialize something else, the compiler won't betray me and do the wrong thing:
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
There's no problem: the call is ambiguous, the code won't compile, and I'll have to pick the overload explicitly.
f(bar { "answer", 42 }); // ok
Since the prohibition is explicitly stated, I have the feeling that I am missing something here. As far as I can see, list initialization picking explicit constructors doesn't seem like a problem to me: by using list initialization syntax the programmer is already expressing the desire to do some kind of "conversion".
What could go wrong? What am I missing?
See Question&Answers more detail:
os