2006. emplace broken for associative containers

Section: 23.2.8 [unord.req] Status: NAD Submitter: Pablo Halpern Opened: 2010-10-18 Last modified: 2016-01-28

Priority: Not Prioritized

View other active issues in [unord.req].

View all other issues in [unord.req].

View all issues with NAD status.

Discussion:

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.

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.

[ 2010 Batavia: ]

N3178 was looked at in session and moved to NAD.

Proposed resolution: