Search code examples
c++c++11language-lawyerobject-constructionlist-initialization

Forwarded in-place construction and list-initialization


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);

Solution

  • 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.

    live example.

    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!