diff mbox

libstdc++/61023 - copy comparison functor in RB tree move assignment

Message ID 20140507141320.GF18109@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely May 7, 2014, 2:13 p.m. UTC
As noted in the PR, the standard doesn't actually say what containers
should do with their functors on move construction/assignment.

Our unordered containers currently move the hash and predicate
functions.

Our RB trees copy the comparison function in the move constructor but
do nothing with it in the move assignment. I think moving in both
cases is probably correct, but rather than change the existing move
constructor this patch just makes the move assignment copy the
function, for consistency.

When the standard is clarified we can review whether we should be
moving instead of copying.

Tested x86_64-linux, committed to trunk and the 4.9 branch.
diff mbox

Patch

commit 42ea108aeb7528ff3b41f7c1b9d11f3a8ba1bae8
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed May 7 14:25:48 2014 +0100

    	PR libstdc++/61023
    	* include/bits/stl_tree.h (_Rb_tree::_M_move_assign): Copy the
    	comparison function.
    	* testsuite/23_containers/set/cons/61023.cc: New.

diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h
index 288c9fa..ce43ab8 100644
--- a/libstdc++-v3/include/bits/stl_tree.h
+++ b/libstdc++-v3/include/bits/stl_tree.h
@@ -1073,6 +1073,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
     _M_move_assign(_Rb_tree& __x)
     {
+      _M_impl._M_key_compare = __x._M_impl._M_key_compare;
       if (_Alloc_traits::_S_propagate_on_move_assign()
 	  || _Alloc_traits::_S_always_equal()
 	  || _M_get_Node_allocator() == __x._M_get_Node_allocator())
diff --git a/libstdc++-v3/testsuite/23_containers/set/cons/61023.cc b/libstdc++-v3/testsuite/23_containers/set/cons/61023.cc
new file mode 100644
index 0000000..087b9cc
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/set/cons/61023.cc
@@ -0,0 +1,56 @@ 
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <set>
+#include <stdexcept>
+
+struct Comparator
+{
+  Comparator() : valid(false) { }
+  explicit Comparator(bool) : valid(true) { }
+
+  bool operator()(int i, int j) const
+  {
+    if (!valid)
+      throw std::logic_error("Comparator is invalid");
+    return i < j;
+  }
+
+private:
+  bool valid;
+};
+
+int main()
+{
+  using test_type = std::set<int, Comparator>;
+
+  Comparator cmp{true};
+
+  test_type good{cmp};
+
+  test_type s1;
+  s1 = good;             // copy-assign
+  s1.insert(1);
+  s1.insert(2);
+
+  test_type s2;
+  s2 = std::move(good);  // move-assign
+  s2.insert(1);
+  s2.insert(2);
+}