For how non-sense this may seem (read below), given the current state of the specification you cannot make any assumption on the state of the argument after the function call returns.
To see why, let's first point out that the insert()
member function is defined in terms of emplace()
(see 23.4.4.4/1):
The first form is equivalent to
return emplace(std::forward<P>(x))
. [...]
The post-conditions of emplace()
are in turn specified as (see § 23.2.4, Table 102):
Inserts a
value_type
objectt
constructed withstd::forward<Args>(args)...
if and only if there is no element in the container with key equivalent to the key oft
. Thebool
component of the returned pair istrue
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 oft
.
The sentence in bold from the above quote (emphasis is mine) says that the pair that will become an element of the map if the key is not already present will be move-constructed directly from the rvalue pair you supply.
This would make it very very reasonable to deduce that implementations will first have to check if the key is present and, only if not, move-construct the new map's element from the your pair.
However, "very very reasonable" is not a valid argument when dealing with the specification of a formal language. In this case, from the formal viewpoint there is nothing that prevents an implementation from doing the following:
- First move-construct a pair
tmp
from your argument (which would mean you can't make assumptions on the state of your argument after the function returns); - Check if the key is already present in the map;
- If not, do the necessary housekeeping to insert
tmp
into the container.
Or even:
- Check if the key is present in the map;
- If so, insert a new element move-constructed from your argument;
- If not, move-construct a new object from your argument and do nothing with it.
Point 3 above is absolutely meaningless, but it is not formally forbidden. Mind the phrasing:
Inserts a
value_type
objectt
constructed withstd::forward<Args>(args)...
if and only if there is no element in the container with key equivalent to the key oft
.
This only says that if there is no element in the container with key equivalent to the key of t
, no object move-constructed from t
will be inserted into the map - but, for how stupid this may sound, it does not say that no object at all shall be move-constructed from t
: as long as it does not get inserted into the map, this is allowed.
This said, since the Standard does not explicitly constrain implementations in this respect, you cannot make assumptions on whether or not your argument was moved from. Consequently, you cannot make assumptions on the state your pair will be in when the function call returns (per paragraph 17.6.5.15).
If I can let a personal opinion sneak in, though, I believe this is a defect.