As others have pointed out in the comments, the "universal" constructor is not, in fact, supposed to always move from its argument. It's supposed to move if the argument is really an rvalue, and copy if it's an lvalue.
The behaviour, you observe, which always moves, is a bug in libstdc++, which is now fixed according to a comment on the question. For those curious, I took a look at the g++-4.8 headers.
bits/stl_map.h
, lines 598-603
template<typename _Pair, typename = typename
std::enable_if<std::is_constructible<value_type,
_Pair&&>::value>::type>
std::pair<iterator, bool>
insert(_Pair&& __x)
{ return _M_t._M_insert_unique(std::forward<_Pair>(__x)); }
bits/unordered_map.h
, lines 365-370
template<typename _Pair, typename = typename
std::enable_if<std::is_constructible<value_type,
_Pair&&>::value>::type>
std::pair<iterator, bool>
insert(_Pair&& __x)
{ return _M_h.insert(std::move(__x)); }
The latter is incorrectly using std::move
where it should be using std::forward
.