2362. unique, associative emplace() should not move/copy the mapped_type constructor arguments when no insertion happens

Section: 23.2.7 [associative.reqmts], 23.2.8 [unord.req] Status: New Submitter: Jeffrey Yasskin Opened: 2014-02-15 Last modified: 2015-09-23

Priority: 3

View other active issues in [associative.reqmts].

View all other issues in [associative.reqmts].

View all issues with New status.

Discussion:

a_uniq.emplace(args) is specified as:

Effects: Inserts a value_type 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.

However, we occasionally find code of the form:

std::unique_ptr<Foo> p(new Foo);
auto res = m.emplace("foo", std::move(p));

where we'd like to avoid destroying the Foo if the insertion doesn't take place (if the container already had an element with the specified key).

N3873 includes a partial solution to this in the form of a new emplace_stable member function, but LEWG's discussion strongly agreed that we'd rather have emplace() Just Work:

Should map::emplace() be guaranteed not to move/copy its arguments if the insertion doesn't happen?

SF: 8 F: 3 N: 0 A: 0 SA: 0

This poll was marred by the fact that we didn't notice or call out that emplace() must construct the key before doing the lookup, and it must not then move the key after it determines whether an insert is going to happen, and the mapped_type instance must live next to the key.

The very similar issue 2006 was previously marked NAD, with N3178 as discussion. However, given LEWG's interest in the alternate behavior, we should reopen the question in this issue.

We will need a paper that describes how to implement this before we can make more progress.

Proposed resolution: