ISO/ IEC JTC1/SC22/WG21 N3178

Document No:    N3178=10-0168
Date:           2010-10-18
Author:         Pablo Halpern, Intel Corp.
                phalpern@halpernwightsoftware.com

        emplace broken for associative containers

Issue:

The current definition of emplace(args) for associative containers as
described in Table 99 is:

    Requires: T shall be constructible from args.

    Effects: Inserts a T object t constructed with std::forward<Args>(args)...
    if and only if there is no element in the container with key equivalent to
    the key of t.  The bool component of the returned pair is true if and only
    if the insertion takes place, and the iterator component of the pair
    points to the element with key equivalent to the key of t.

There is similar language in Table 100 for unordered associative containers.

The first issue is editorial "T" should be "value_type" throughout both
tables.

The major issue is that, If the container is map, multimap, unordered_map, or
unordered_multimap, then the only way to construct an object of value_type is
to supply exactly two arguments for Key and Value, a pair<Key,Value>, or a
piecewise_construct_t followed by two tuples.  The original emplace() proposal
would have allowed you to specify a Key value followed by any number of
constructor arguments for Value.  When we removed the variadic constructor to
pair, this ability went away.  I don't think that was deliberate.

Proposed resolution:

Fixing this is non-trivial, I think. I think that emplace() for map and
multimap need several overloads: one for each overloaded constructor in
pair<Key,Value>, and one for the emplace(Key, valueargs...) case.  And it
probably needs some sfinae meta-programming to ensure that the last case
doesn't override any of the other ones.  Alternatively, one could say that
there are exactly two cases: emplace(args) where pair<Key,Value> is
constructible from args, and emplace(args) where Key is constructible form the
first arg and Value is constructible from the rest.

Alternatively, the status quo is to use piecewise_construct_t if you want to
construct an object.