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.
commit 42ea108aeb7528ff3b41f7c1b9d11f3a8ba1bae8 Author: Jonathan Wakely <jwak...@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); +}