What makes you run aggregate initialization.
As you say, there are advantages and disadvantages to using list initialization. (The term "uniform initialization" is not used by the C ++ standard).
One of the drawbacks is that list initialization behaves differently for aggregates than non-aggregates. In addition, the definition of population varies slightly with each standard.
Aggregates are not created using the constructor. (Technically, they may actually be, but this is a good way to think about it). Instead, when creating an aggregate, memory is allocated, and then each element is initialized in the order that corresponds to what is in the list initializer.
Non-aggregators are created through constructors, in which case the constructor arguments are members of the list initializer.
Actually, there is a design flaw: if we have T t1; T t2{t1}; T t1; T t2{t1}; , then the goal is to perform copy-construction. However (before C ++ 14), if T is an aggregate, then the aggregate is initialized instead, and t2 first element is initialized with t1 .
This flaw was recorded in the defect report, which changed with C ++ 14, therefore, from now on, copying is checked before we proceed to aggregate initialization.
Aggregate definition from C ++ 14:
An aggregate is an array or class (section 9) without constructors provided by the user (12.1), without private or protected non-static data elements (section 11), without base classes (section 10) and without virtual functions (10.3).
In C ++ 11, the default value for a non-static element means that the class is not an aggregate; however, this has been changed for C ++ 14. User means means declared by the user, but not = default or = delete .
If you want your constructor call to never perform aggregate initialization, you should use ( ) rather than { } and avoid MVP in other ways.