https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78595
--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> --- For example: --- a/libstdc++-v3/include/bits/stl_map.h +++ b/libstdc++-v3/include/bits/stl_map.h @@ -795,12 +795,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { return _M_t._M_insert_unique(__x); } #if __cplusplus >= 201103L - template<typename _Pair, typename = typename - std::enable_if<std::is_constructible<value_type, - _Pair&&>::value>::type> + std::pair<iterator, bool> + insert(value_type&& __x) + { return _M_t._M_insert_unique(std::move(__x)); } + + template<typename _Pair> + using _Insertable + = _Require<__not_<is_same<typename decay<_Pair>::type, value_type>>, + is_constructible<value_type, _Pair>>; + + template<typename _Pair, typename = _Insertable<_Pair>> std::pair<iterator, bool> insert(_Pair&& __x) - { return _M_t._M_insert_unique(std::forward<_Pair>(__x)); } + { return _M_t._M_insert_unique(value_type(__x)); } #endif #if __cplusplus >= 201103L We could also add a static assertion in _Rb_tree::_M_insert_unique to ensure it's only called with value_type arguments, so we know the caller has done any necessary conversions to avoid temporaries. For multimap/multiset we probably want to do things differently, and just change _M_insert_equal to allocate the node first and construct the element into it, and get the key directly from the constructed element.