I have the following constructor:
MyItem(std::initializer_list<double> l) {
std::cout << "l size " << l.size() << ")" << std::endl;
}
Which is called later with double curly braces:
MyItem{{}}
The result l.size() gives is 1.
What's the mechanics behind such behavior?
It seems like nested {} plays like a default constructor for the only element, but I don't quite understand why and how type deduction works here.
When you use braces (list-initialization) to initialize the MyItem object, the list constructor you have shown is very greedy.
These would pass an empty list:
MyItem foo({});
MyItem foo{std::initializer_list<double>{}};
This passes a list containing a single element - a value-initialized double (0.0):
MyItem foo{{}};
This works because there are certain contexts where you can simply use braces in place of a known type. Here, it knows from preferring the list constructor that the given list should contain double.
For completeness, this looks like it passes an empty list, but it actually value-initializes foo if it has a default constructor (or in special cases, does something almost equivalent). If there's no default constructor, it would choose the list constructor, as shown here.
MyItem foo{};
This expression
MyItem{{}}
denotes explicit type conversion (the functional notation).
According to the C++ Standard (5.2.3 Explicit type conversion (functional notation))
- Similarly, a simple-type-specifier or typename-specifier followed by a braced-init-list creates a temporary object of the specified type direct-list-initialized (8.5.4) with the specified braced-init-list, and its value is that temporary object as a prvalue.
Class MyItem has conversion initializer-list constructor
MyItem(std::initializer_list<double> l) {
std::cout << "l size " << l.size() << ")" << std::endl;
}
that is selected for the explicit type conversion. In fact it is equivalent to the call
MyItem( {{}} );
So the constructor gets an initializer list with one element
{ {} }
A scalar object of type double can be initialized with an empty braces {}.
As result the expression creates a temporary object of type MyItem which is initialized by an initializer list that contains one element of type double that is value-initialized by means of empty braces.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With