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{};