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