Consider the code
#include <iostream>
class Foo
{
int val_;
public:
Foo(std::initializer_list<Foo> il)
{
std::cout << "initializer_list ctor" << std::endl;
}
/* explicit */ Foo(int val): val_(val)
{
std::cout << "ctor" << std::endl;
};
};
int main(int argc, char const *argv[])
{
// why is the initializer_list ctor invoked?
Foo foo {10};
}
The output is
ctor
initializer_list ctor
As far as I understand, the value 10
is implicitly converted to a Foo
(first ctor
output), then the initializer constructor kicks in (second initializer_list ctor
output). My question is why is this happening? Isn't the standard constructor Foo(int)
a better match? I.e., I would have expected the output of this snippet to be just ctor
.
PS: If I mark the constructor Foo(int)
as explicit
, then Foo(int)
is the only constructor invoked, as the integer 10
cannot now be implicitly converted to a Foo
.
The n2100 proposal for initializer lists goes into great detail about the decision to make sequence constructors (what they call constructors that take
std::initializer_lists
) to have priority over regular constructors. See Appendix B for a detailed discussion. It's succinctly summarized in the conclusion:§13.3.1.7 [over.match.list]/p1:
As long as there is a viable initializer-list constructor, it will trump all non-initializer-list constructors when list-initialization is used and the initializer list has at least one element.
The whole initializer list thing was meant to enable list initialisation like so:
Consider the case
That this initializes the vector with one element of value 123 rather than 123 elements of value zero is intended.
To access the other constructor, use the old syntax