2018-09-03 Jonathan Wakely <jwakely@redhat.com>
+ PR libstdc++/87194
+ * include/bits/stl_map.h
+ (map::map(initializer_list<value_type>, const Compare&, const Alloc&))
+ (map::map(initializer_list<value_type>, const Alloc&))
+ (map::map(InputIterator, InputIterator, const Alloc&))
+ (map::map(InputIterator, InputIterator))
+ (map::map(InputIterator, InputIterator, const Compare&, const Alloc&))
+ (map::insert(InputIterator, InputIterator)):
+ Call _M_insert_range_unique instead of _M_insert_unique.
+ * include/bits/stl_multimap.h
+ (multimap::multimap(initializer_list<value_type>, const C&, const A&))
+ (multimap::multimap(initializer_list<value_type>, const A&))
+ (multimap::multimap(InputIterator, InputIterator, const A&))
+ (multimap::multimap(InputIterator, InputIterator))
+ (multimap::multimap(InputIterator, InputIterator, const C&, const A&))
+ (multimap::insert(InputIterator, InputIterator)): Call
+ _M_insert_range_equal instead of _M_insert_equal.
+ * include/bits/stl_multiset.h
+ (multiset::multiset(InputIterator, InputIterator))
+ (multiset::multiset(InputIterator, InputIterator, const C&, const A&))
+ (multiset::multiset(initializer_list<value_type>, const C&, const A&))
+ (multiset::multiset(initializer_list<value_type>, const A&))
+ (multiset::multiset(InputIterator, InputIterator, const A&))
+ (multiset::insert(InputIterator, InputIterator)): Call
+ _M_insert_range_equal instead of _M_insert_equal.
+ * include/bits/stl_set.h
+ (set::set(InputIterator, InputIterator))
+ (set::set(InputIterator, InputIterator, const Compare&, const Alloc&))
+ (set::set(initializer_list<value_type>, const Compare&, const Alloc&))
+ (set::set(initializer_list<value_type>, const Alloc&))
+ (set::set(InputIterator, InputIterator, const Alloc&))
+ (set::insert(InputIterator, InputIterator)):
+ Call _M_insert_range_unique instead of _M_insert_unique.
+ * include/bits/stl_tree.h
+ [__cplusplus >= 201103L] (_Rb_tree::__same_value_type): New alias
+ template for SFINAE constraints.
+ [__cplusplus >= 201103L] (_Rb_tree::_M_insert_range_unique): Pair of
+ constrained overloads that either insert or emplace, depending on
+ iterator's value_type.
+ [__cplusplus >= 201103L] (_Rb_tree::_M_insert_range_equal): Likewise.
+ [__cplusplus < 201103L] (_Rb_tree::_M_insert_range_unique)
+ (_Rb_tree::_M_insert_range_equal): New functions replacing range
+ versions of _M_insert_unique and _M_insert_equal.
+ (_Rb_tree::_M_insert_unique(_InputIterator, _InputIterator))
+ (_Rb_tree::_M_insert_equal(_InputIterator, _InputIterator)): Remove.
+ * testsuite/23_containers/map/modifiers/insert/87194.cc: New test.
+ * testsuite/23_containers/multimap/modifiers/insert/87194.cc: New test.
+ * testsuite/23_containers/multiset/modifiers/insert/87194.cc: New test.
+ * testsuite/23_containers/set/modifiers/insert/87194.cc: New test.
+
PR libstdc++/78595
* include/bits/stl_map.h (map::insert(_Pair&&))
(map::insert(const_iterator, _Pair&&)): Do emplace instead of insert.
const _Compare& __comp = _Compare(),
const allocator_type& __a = allocator_type())
: _M_t(__comp, _Pair_alloc_type(__a))
- { _M_t._M_insert_unique(__l.begin(), __l.end()); }
+ { _M_t._M_insert_range_unique(__l.begin(), __l.end()); }
/// Allocator-extended default constructor.
explicit
/// Allocator-extended initialier-list constructor.
map(initializer_list<value_type> __l, const allocator_type& __a)
: _M_t(_Pair_alloc_type(__a))
- { _M_t._M_insert_unique(__l.begin(), __l.end()); }
+ { _M_t._M_insert_range_unique(__l.begin(), __l.end()); }
/// Allocator-extended range constructor.
template<typename _InputIterator>
map(_InputIterator __first, _InputIterator __last,
const allocator_type& __a)
: _M_t(_Pair_alloc_type(__a))
- { _M_t._M_insert_unique(__first, __last); }
+ { _M_t._M_insert_range_unique(__first, __last); }
#endif
/**
template<typename _InputIterator>
map(_InputIterator __first, _InputIterator __last)
: _M_t()
- { _M_t._M_insert_unique(__first, __last); }
+ { _M_t._M_insert_range_unique(__first, __last); }
/**
* @brief Builds a %map from a range.
const _Compare& __comp,
const allocator_type& __a = allocator_type())
: _M_t(__comp, _Pair_alloc_type(__a))
- { _M_t._M_insert_unique(__first, __last); }
+ { _M_t._M_insert_range_unique(__first, __last); }
#if __cplusplus >= 201103L
/**
template<typename _InputIterator>
void
insert(_InputIterator __first, _InputIterator __last)
- { _M_t._M_insert_unique(__first, __last); }
+ { _M_t._M_insert_range_unique(__first, __last); }
#if __cplusplus > 201402L
#define __cpp_lib_map_insertion 201411
const _Compare& __comp = _Compare(),
const allocator_type& __a = allocator_type())
: _M_t(__comp, _Pair_alloc_type(__a))
- { _M_t._M_insert_equal(__l.begin(), __l.end()); }
+ { _M_t._M_insert_range_equal(__l.begin(), __l.end()); }
/// Allocator-extended default constructor.
explicit
/// Allocator-extended initialier-list constructor.
multimap(initializer_list<value_type> __l, const allocator_type& __a)
: _M_t(_Pair_alloc_type(__a))
- { _M_t._M_insert_equal(__l.begin(), __l.end()); }
+ { _M_t._M_insert_range_equal(__l.begin(), __l.end()); }
/// Allocator-extended range constructor.
template<typename _InputIterator>
multimap(_InputIterator __first, _InputIterator __last,
const allocator_type& __a)
: _M_t(_Pair_alloc_type(__a))
- { _M_t._M_insert_equal(__first, __last); }
+ { _M_t._M_insert_range_equal(__first, __last); }
#endif
/**
template<typename _InputIterator>
multimap(_InputIterator __first, _InputIterator __last)
: _M_t()
- { _M_t._M_insert_equal(__first, __last); }
+ { _M_t._M_insert_range_equal(__first, __last); }
/**
* @brief Builds a %multimap from a range.
const _Compare& __comp,
const allocator_type& __a = allocator_type())
: _M_t(__comp, _Pair_alloc_type(__a))
- { _M_t._M_insert_equal(__first, __last); }
+ { _M_t._M_insert_range_equal(__first, __last); }
#if __cplusplus >= 201103L
/**
template<typename _InputIterator>
void
insert(_InputIterator __first, _InputIterator __last)
- { _M_t._M_insert_equal(__first, __last); }
+ { _M_t._M_insert_range_equal(__first, __last); }
#if __cplusplus >= 201103L
/**
template<typename _InputIterator>
multiset(_InputIterator __first, _InputIterator __last)
: _M_t()
- { _M_t._M_insert_equal(__first, __last); }
+ { _M_t._M_insert_range_equal(__first, __last); }
/**
* @brief Builds a %multiset from a range.
const _Compare& __comp,
const allocator_type& __a = allocator_type())
: _M_t(__comp, _Key_alloc_type(__a))
- { _M_t._M_insert_equal(__first, __last); }
+ { _M_t._M_insert_range_equal(__first, __last); }
/**
* @brief %Multiset copy constructor.
const _Compare& __comp = _Compare(),
const allocator_type& __a = allocator_type())
: _M_t(__comp, _Key_alloc_type(__a))
- { _M_t._M_insert_equal(__l.begin(), __l.end()); }
+ { _M_t._M_insert_range_equal(__l.begin(), __l.end()); }
/// Allocator-extended default constructor.
explicit
/// Allocator-extended initialier-list constructor.
multiset(initializer_list<value_type> __l, const allocator_type& __a)
: _M_t(_Key_alloc_type(__a))
- { _M_t._M_insert_equal(__l.begin(), __l.end()); }
+ { _M_t._M_insert_range_equal(__l.begin(), __l.end()); }
/// Allocator-extended range constructor.
template<typename _InputIterator>
multiset(_InputIterator __first, _InputIterator __last,
const allocator_type& __a)
: _M_t(_Key_alloc_type(__a))
- { _M_t._M_insert_equal(__first, __last); }
+ { _M_t._M_insert_range_equal(__first, __last); }
/**
* The dtor only erases the elements, and note that if the elements
template<typename _InputIterator>
void
insert(_InputIterator __first, _InputIterator __last)
- { _M_t._M_insert_equal(__first, __last); }
+ { _M_t._M_insert_range_equal(__first, __last); }
#if __cplusplus >= 201103L
/**
template<typename _InputIterator>
set(_InputIterator __first, _InputIterator __last)
: _M_t()
- { _M_t._M_insert_unique(__first, __last); }
+ { _M_t._M_insert_range_unique(__first, __last); }
/**
* @brief Builds a %set from a range.
const _Compare& __comp,
const allocator_type& __a = allocator_type())
: _M_t(__comp, _Key_alloc_type(__a))
- { _M_t._M_insert_unique(__first, __last); }
+ { _M_t._M_insert_range_unique(__first, __last); }
/**
* @brief %Set copy constructor.
const _Compare& __comp = _Compare(),
const allocator_type& __a = allocator_type())
: _M_t(__comp, _Key_alloc_type(__a))
- { _M_t._M_insert_unique(__l.begin(), __l.end()); }
+ { _M_t._M_insert_range_unique(__l.begin(), __l.end()); }
/// Allocator-extended default constructor.
explicit
/// Allocator-extended initialier-list constructor.
set(initializer_list<value_type> __l, const allocator_type& __a)
: _M_t(_Key_alloc_type(__a))
- { _M_t._M_insert_unique(__l.begin(), __l.end()); }
+ { _M_t._M_insert_range_unique(__l.begin(), __l.end()); }
/// Allocator-extended range constructor.
template<typename _InputIterator>
set(_InputIterator __first, _InputIterator __last,
const allocator_type& __a)
: _M_t(_Key_alloc_type(__a))
- { _M_t._M_insert_unique(__first, __last); }
+ { _M_t._M_insert_range_unique(__first, __last); }
/**
* The dtor only erases the elements, and note that if the elements
template<typename _InputIterator>
void
insert(_InputIterator __first, _InputIterator __last)
- { _M_t._M_insert_unique(__first, __last); }
+ { _M_t._M_insert_range_unique(__first, __last); }
#if __cplusplus >= 201103L
/**
template<typename... _Args>
iterator
_M_emplace_hint_equal(const_iterator __pos, _Args&&... __args);
+
+ template<typename _Iter>
+ using __same_value_type
+ = is_same<value_type, typename iterator_traits<_Iter>::value_type>;
+
+ template<typename _InputIterator>
+ __enable_if_t<__same_value_type<_InputIterator>::value>
+ _M_insert_range_unique(_InputIterator __first, _InputIterator __last)
+ {
+ _Alloc_node __an(*this);
+ for (; __first != __last; ++__first)
+ _M_insert_unique_(end(), *__first, __an);
+ }
+
+ template<typename _InputIterator>
+ __enable_if_t<!__same_value_type<_InputIterator>::value>
+ _M_insert_range_unique(_InputIterator __first, _InputIterator __last)
+ {
+ for (; __first != __last; ++__first)
+ _M_emplace_unique(*__first);
+ }
+
+ template<typename _InputIterator>
+ __enable_if_t<__same_value_type<_InputIterator>::value>
+ _M_insert_range_equal(_InputIterator __first, _InputIterator __last)
+ {
+ _Alloc_node __an(*this);
+ for (; __first != __last; ++__first)
+ _M_insert_equal_(end(), *__first, __an);
+ }
+
+ template<typename _InputIterator>
+ __enable_if_t<!__same_value_type<_InputIterator>::value>
+ _M_insert_range_equal(_InputIterator __first, _InputIterator __last)
+ {
+ _Alloc_node __an(*this);
+ for (; __first != __last; ++__first)
+ _M_emplace_equal(*__first);
+ }
#else
pair<iterator, bool>
_M_insert_unique(const value_type& __x);
_Alloc_node __an(*this);
return _M_insert_equal_(__pos, __x, __an);
}
-#endif
template<typename _InputIterator>
void
- _M_insert_unique(_InputIterator __first, _InputIterator __last);
+ _M_insert_range_unique(_InputIterator __first, _InputIterator __last)
+ {
+ _Alloc_node __an(*this);
+ for (; __first != __last; ++__first)
+ _M_insert_unique_(end(), *__first, __an);
+ }
template<typename _InputIterator>
void
- _M_insert_equal(_InputIterator __first, _InputIterator __last);
+ _M_insert_range_equal(_InputIterator __first, _InputIterator __last)
+ {
+ _Alloc_node __an(*this);
+ for (; __first != __last; ++__first)
+ _M_insert_equal_(end(), *__first, __an);
+ }
+#endif
private:
void
}
#endif
- template<typename _Key, typename _Val, typename _KoV,
- typename _Cmp, typename _Alloc>
- template<class _II>
- void
- _Rb_tree<_Key, _Val, _KoV, _Cmp, _Alloc>::
- _M_insert_unique(_II __first, _II __last)
- {
- _Alloc_node __an(*this);
- for (; __first != __last; ++__first)
- _M_insert_unique_(end(), *__first, __an);
- }
-
- template<typename _Key, typename _Val, typename _KoV,
- typename _Cmp, typename _Alloc>
- template<class _II>
- void
- _Rb_tree<_Key, _Val, _KoV, _Cmp, _Alloc>::
- _M_insert_equal(_II __first, _II __last)
- {
- _Alloc_node __an(*this);
- for (; __first != __last; ++__first)
- _M_insert_equal_(end(), *__first, __an);
- }
template<typename _Key, typename _Val, typename _KeyOfValue,
typename _Compare, typename _Alloc>
--- /dev/null
+// Copyright (C) 2018 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/>.
+
+// { dg-do run { target c++11 } }
+
+#include <map>
+#include <iterator>
+#include <testsuite_hooks.h>
+
+struct S
+{
+ operator std::pair<const int, int>() &&
+ { int i = val; val = 0; return {i, 0}; }
+
+ int val;
+};
+
+void
+test01()
+{
+ S a[3] = { {1}, {2}, {3} };
+ std::map<int, int> s;
+ s.insert(std::make_move_iterator(a), std::make_move_iterator(a+3));
+ VERIFY( s.size() == 3 );
+ VERIFY( s.find(0) == s.end() );
+}
+
+int
+main()
+{
+ test01();
+}
--- /dev/null
+// Copyright (C) 2018 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/>.
+
+// { dg-do run { target c++11 } }
+
+#include <map>
+#include <iterator>
+#include <testsuite_hooks.h>
+
+struct S
+{
+ operator std::pair<const int, int>() &&
+ { int i = val; val = 0; return {i, 0}; }
+
+ int val;
+};
+
+void
+test01()
+{
+ S a[3] = { {1}, {2}, {3} };
+ std::multimap<int, int> s;
+ s.insert(std::make_move_iterator(a), std::make_move_iterator(a+3));
+ VERIFY( s.size() == 3 );
+ VERIFY( s.find(0) == s.end() );
+}
+
+int
+main()
+{
+ test01();
+}
--- /dev/null
+// Copyright (C) 2018 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/>.
+
+// { dg-do run { target c++11 } }
+
+#include <set>
+#include <iterator>
+#include <testsuite_hooks.h>
+
+struct S {
+ S(int v) : val(v) {}
+ operator int() && { int i = val; val = 0; return i; }
+ int val;
+};
+
+void
+test01()
+{
+ S a[3] = { {1}, {2}, {3} };
+ std::multiset<int> s;
+ s.insert(std::make_move_iterator(a), std::make_move_iterator(a+3));
+ VERIFY( s.size() == 3 );
+ VERIFY( s.find(0) == s.end() );
+}
+
+int
+main()
+{
+ test01();
+}
--- /dev/null
+// Copyright (C) 2018 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/>.
+
+// { dg-do run { target c++11 } }
+
+#include <set>
+#include <iterator>
+#include <testsuite_hooks.h>
+
+struct S {
+ S(int v) : val(v) {}
+ operator int() && { int i = val; val = 0; return i; }
+ int val;
+};
+
+void
+test01()
+{
+ S a[3] = { {1}, {2}, {3} };
+ std::set<int> s;
+ s.insert(std::make_move_iterator(a), std::make_move_iterator(a+3));
+ VERIFY( s.size() == 3 );
+ VERIFY( s.find(0) == s.end() );
+}
+
+int
+main()
+{
+ test01();
+}