5

I have a set of objects, and I want to use emplace to add objects to the set. If an equivalent object does not already exist in the set, set::emplace creates an object and puts it in the set. If the set already has an equivalent object, set::emplace does not add an object to the list. In this case, does it create the object and destroy it, create it and leak it, or not create it at all? Or will it do something else?

C++ 11, gcc 4.7.0

Qaz
  • 1,556
  • 2
  • 20
  • 34

2 Answers2

3

From § 23.2.4 Table 102 — Associative container requirements (in addition to container)

emplace(args)

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.

user657267
  • 20,568
  • 5
  • 58
  • 77
3

It's not supposed to construct the object at all, but it generally will anyway (certainly using libstd++); this is technically a bug, but more so in the standard than anything else.

Fuller details can be found in a previous answer of mine to a very similar question:

Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 2
    If it does not construct an object, how can it test whether the object exists in the set? I read your answer on the other question, and the linked isocpp discussion, and I can't see how it relates. In the discussion, you seem to be talking about constructing the value part of a key/value pair of a map. This is about constructing a key, and I don't see how it can be avoided (but am very interested in being shown). – Benjamin Lindley Mar 27 '14 at 02:01
  • 1
    I dispute your claim that `emplace` is required not to construct an object when the insertion fails. The wording is "Inserts [an object] constructed with [stuff] if and only if [conditions]", it is not "Constructs and inserts [an object] from [stuff] if and only if [conditions]." The use of past tense for "constructed" and present tense for "inserts" indicates that such construction necessarily must have occurred before the checking of the conditions and possible insertion. – Casey Mar 27 '14 at 05:03
  • 1
    The wording could certainly be clearer, but your statement about "a bug " in "certain versions of GCC" implies that the wording is clear and that libstdc++ is non-compliant, which I think we can at least agree is not the case. Given that it's possible to specialize `std::pair`, it is easy to show that determining the key of the constructed object from the arguments to `emplace` is in general undecidable. I don't think the standard could reasonably require an implementation to always avoid the construction when the insertion is not performed. – Casey Mar 27 '14 at 05:11
  • @BenjaminLindley: The hope was that only the key be constructed for comparisons, not the entire mapped value. I'll grant that the standard's restriction seems intractible but I maintain that this is what the current wording clearly states. – Lightness Races in Orbit Mar 27 '14 at 09:33
  • (^ in the case of maps, anyway) – Lightness Races in Orbit Mar 27 '14 at 14:22
  • 1
    The obvious solution would have been to make a comparator that accepts the args to be forwarded to the constructor, rather than an actual constructed object. However, I don't see anything like that in the docs. – Chris Feb 21 '16 at 18:50