[Bug libstdc++/78595] Unnecessary copies in _Rb_tree

redi at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Tue Nov 29 19:30:00 GMT 2016


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.


More information about the Gcc-bugs mailing list