Though std::move
does not actually perform any move, and neither does std::make_pair
, std::make_pair
forwards its arguments to the std::pair
constructor, which initialises its two value members from those arguments.
As such, the move is performed at that point, before the std::map
has a chance to do anything. So, yes, you end up with a "broken" move for no good reason.
You should be able to take advantage of emplace
(in order to skip the pair construction). From Table 102:
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
.
Clearly, the library is still "forwarding" at this point so it's pre-move, and in your case no emplace shall take place so the entire expression ought to be an effective no-op.
However, libstdc++ from GCC 4.8.0 appears to have a bug in this regard: emplace
invokes _M_emplace_unique
on the internal tree, which forwards the arguments to _M_create_node
, which forwards the arguments to allocator_traits<_Node_allocator>::construct
, which forwards the arguments to _S_construct
, which forwards the arguments to __a.construct
which, with the default allocator, is std::allocator<std::pair<const _Key, _Tp> >::construct
, which is the pair constructor you were trying to avoid... all before the collision check in _M_emplace_unique
.
It could be claimed that the standard is ambiguous in this regard, but I'd call it a violation of intent. Then again, clang v3.4 with libc++ exhibits this behaviour too, as does Visual Studio 2012. So if my standard interpretation is correct, this fails on all three of the mainstream toolchains.
I guess they all decided that the "if and only if" applied to the insertion, rather than the insertion and the construction.
I have posted a question on std-discussion aiming to provoke an improvement to the passage from Table 102 to authoritatively answer this once and for all.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…