By forwarded in-place construction, I take to mean std::allocator::construct and the various emplace methods, e.g., std::vector::emplace_back. I just find that forwarded in-place construction in C++ does not (unable to?) take advantage of the list-initialization syntax. As a result, it seems one can never forward in-place construct an aggregate. I just want to make sure whether forwarded in-place construction does not support list-initialization and hence aggregate types. Is this due to the limitation of the language? Could someone provide reference to the standard concerning this issue? Following is an illustration:
While we can do in-place construction directly like
int(*p)[3] = ...;
new(p) int[3]{1, 2, 3};
we cannot do forwarded in-place construction like
std::allocator<int[3]> allo;
allo.construct(p, 1, 2, 3);
While {}
has been called uniform initialization syntax, it is far from universal.
take these two examples:
size_t a = 3;
size_t b = 1;
std::vector<size_t> v1{a,b};
std::vector<size_t> v2(a,b);
in the first case, we construct a vector containing two elements, 3
and 1
.
In the second case, we create a vector containing 1,1,1
-- 3 copies of 1
.
So {}
based construction can cause a different behavior than ()
based construction in some cases. What more, in the above case, there is no way to reach the "3 copies of 1" syntax using {}
construction (that I know of). But the {3,2}
case can be handled by simply explicitly creating an initializer list and passing it to ()
.
As most types that take initializer lists can be emplace constructed by explicitly passing in an initializer list, and the C++ standard library was designed for types with constructors more than types without them, the C++ standard library nearly uniformly emplace constructs using ()
and not {}
.
The downside is that types that want to be list-initialized cannot be emplaced via this mechanism.
In theory, list_emplace
methods that construct using {}
instead could be added to each interface. I encourage you to propose that!