Implement C++17 node extraction and insertion (P0083R5)

* doc/xml/manual/status_cxx2017.xml: Document status.
	* doc/html/*: Regenerate.
	* include/Makefile.am: Add bits/node_handle.h and reorder.
	* include/Makefile.in: Regenerate.
	* include/bits/hashtable.h (_Hashtable::node_type)
	(_Hashtable::insert_return_type, _Hashtable::_M_reinsert_node)
	(_Hashtable::_M_reinsert_node_multi, _Hashtable::extract)
	(_Hashtable::_M_merge_unique, _Hashtable::_M_merge_multi): Define.
	(_Hash_merge_helper): Define primary template.
	* include/bits/node_handle.h: New header.
	* include/bits/stl_map.h (map): Declare _Rb_tree_merge_helper as
	friend.
	(map::node_type, map::insert_return_type, map::extract, map::merge)
	(map::insert(node_type&&), map::insert(const_iterator, node_type&&)):
	Define new members.
	(_Rb_tree_merge_helper): Specialize for map.
	* include/bits/stl_multimap.h (multimap): Declare _Rb_tree_merge_helper
	as friend.
	(multimap::node_type, multimap::extract, multimap::merge)
	(multimap::insert(node_type&&))
	(multimap::insert(const_iterator, node_type&&)): Define.
	(_Rb_tree_merge_helper): Specialize for multimap.
	* include/bits/stl_multiset.h (multiset): Declare _Rb_tree_merge_helper
	as friend.
	(multiset::node_type, multiset::extract, multiset::merge)
	(multiset::insert(node_type&&))
	(multiset::insert(const_iterator, node_type&&)): Define.
	* include/bits/stl_set.h (set): Declare _Rb_tree_merge_helper as
	friend.
	(set::node_type, set::insert_return_type, set::extract, set::merge)
	(set::insert(node_type&&), set::insert(const_iterator, node_type&&)):
	Define.
	(_Rb_tree_merge_helper): Specialize for set.
	* include/bits/stl_tree.h (_Rb_tree): Declare _Rb_tree<> as friend.
	(_Rb_tree::node_type, _Rb_tree::insert_return_type)
	(_Rb_tree::_M_reinsert_node_unique, _Rb_tree::_M_reinsert_node_equal)
	(_Rb_tree::_M_reinsert_node_hint_unique)
	(_Rb_tree::_M_reinsert_node_hint_equal, _Rb_tree::extract)
	(_Rb_tree::_M_merge_unique, _Rb_tree::_M_merge_equal): Define.
	(_Rb_tree_merge_helper): Specialize for multiset.
	* include/bits/unordered_map.h (unordered_map): Declare
	unordered_map<> and unordered_multimap<> as friends.
	(unordered_map::node_type, unordered_map::insert_return_type)
	(unordered_map::extract, unordered_map::merge)
	(unordered_map::insert(node_type&&))
	(unordered_map::insert(const_iterator, node_type&&))
	(unordered_multimap): Declare _Hash_merge_helper as friend.
	(unordered_multimap::node_type, unordered_multimap::extract)
	(unordered_multimap::merge, unordered_multimap::insert(node_type&&))
	(unordered_multimap::insert(const_iterator, node_type&&)): Define.
	(_Hash_merge_helper): Specialize for unordered maps and multimaps.
	* include/bits/unordered_set.h (unordered_set, unordered_multiset):
	Declare _Hash_merge_helper as friend.
	(unordered_set::node_type, unordered_set::insert_return_type)
	(unordered_set::extract, unordered_set::merge)
	(unordered_set::insert(node_type&&))
	(unordered_set::insert(const_iterator, node_type&&)): Define.
	(unordered_multiset::node_type, unordered_multiset::extract)
	(unordered_multiset::merge, unordered_multiset::insert(node_type&&))
	(unordered_multiset::insert(const_iterator, node_type&&)): Define.
	(_Hash_merge_helper): Specialize for unordered sets and multisets.
	* include/debug/map.h (map): Add using declarations or forwarding
	functions for new members.
	* include/debug/map.h (multimap): Likewise.
	* include/debug/map.h (multiset): Likewise.
	* include/debug/map.h (set): Likewise.
	* include/debug/unordered_map (unordered_map, unordered_multimap):
	Likewise.
	* include/debug/unordered_set( unordered_set, unordered_multiset):
	Likewise.
	* python/libstdcxx/v6/printers.py (get_value_from_aligned_membuf): New
	helper function.
	(get_value_from_list_node, get_value_from_Rb_tree_node): Use helper.
	(StdNodeHandlePrinter): Define printer for node handles.
	(build_libstdcxx_dictionary): Register StdNodeHandlePrinter.
	* testsuite/23_containers/map/modifiers/extract.cc: New.
	* testsuite/23_containers/map/modifiers/merge.cc: New.
	* testsuite/23_containers/multimap/modifiers/extract.cc: New.
	* testsuite/23_containers/multimap/modifiers/merge.cc: New.
	* testsuite/23_containers/multiset/modifiers/extract.cc: New.
	* testsuite/23_containers/multiset/modifiers/merge.cc: New.
	* testsuite/23_containers/set/modifiers/extract.cc: New.
	* testsuite/23_containers/set/modifiers/merge.cc: New.
	* testsuite/23_containers/unordered_map/modifiers/extract.cc: New.
	* testsuite/23_containers/unordered_map/modifiers/merge.cc: New.
	* testsuite/23_containers/unordered_multimap/modifiers/extract.cc:
	New.
	* testsuite/23_containers/unordered_multimap/modifiers/merge.cc: New.
	* testsuite/23_containers/unordered_multiset/modifiers/extract.cc:
	New.
	* testsuite/23_containers/unordered_multiset/modifiers/merge.cc: New.
	* testsuite/23_containers/unordered_set/modifiers/extract.cc: New.
	* testsuite/23_containers/unordered_set/modifiers/merge.cc: New.
	* testsuite/23_containers/unordered_set/instantiation_neg.cc: Adjust
	dg-error lineno.
	* testsuite/libstdc++-prettyprinters/cxx17.cc: Test node handles.

From-SVN: r240363
This commit is contained in:
Jonathan Wakely 2016-09-22 14:58:49 +01:00 committed by Jonathan Wakely
parent 475edec070
commit 2dbe56bdfb
40 changed files with 4019 additions and 22 deletions

View File

@ -1,3 +1,103 @@
2016-09-22 Jonathan Wakely <jwakely@redhat.com>
Implement C++17 node extraction and insertion (P0083R5)
* doc/xml/manual/status_cxx2017.xml: Document status.
* doc/html/*: Regenerate.
* include/Makefile.am: Add bits/node_handle.h and reorder.
* include/Makefile.in: Regenerate.
* include/bits/hashtable.h (_Hashtable::node_type)
(_Hashtable::insert_return_type, _Hashtable::_M_reinsert_node)
(_Hashtable::_M_reinsert_node_multi, _Hashtable::extract)
(_Hashtable::_M_merge_unique, _Hashtable::_M_merge_multi): Define.
(_Hash_merge_helper): Define primary template.
* include/bits/node_handle.h: New header.
* include/bits/stl_map.h (map): Declare _Rb_tree_merge_helper as
friend.
(map::node_type, map::insert_return_type, map::extract, map::merge)
(map::insert(node_type&&), map::insert(const_iterator, node_type&&)):
Define new members.
(_Rb_tree_merge_helper): Specialize for map.
* include/bits/stl_multimap.h (multimap): Declare _Rb_tree_merge_helper
as friend.
(multimap::node_type, multimap::extract, multimap::merge)
(multimap::insert(node_type&&))
(multimap::insert(const_iterator, node_type&&)): Define.
(_Rb_tree_merge_helper): Specialize for multimap.
* include/bits/stl_multiset.h (multiset): Declare _Rb_tree_merge_helper
as friend.
(multiset::node_type, multiset::extract, multiset::merge)
(multiset::insert(node_type&&))
(multiset::insert(const_iterator, node_type&&)): Define.
* include/bits/stl_set.h (set): Declare _Rb_tree_merge_helper as
friend.
(set::node_type, set::insert_return_type, set::extract, set::merge)
(set::insert(node_type&&), set::insert(const_iterator, node_type&&)):
Define.
(_Rb_tree_merge_helper): Specialize for set.
* include/bits/stl_tree.h (_Rb_tree): Declare _Rb_tree<> as friend.
(_Rb_tree::node_type, _Rb_tree::insert_return_type)
(_Rb_tree::_M_reinsert_node_unique, _Rb_tree::_M_reinsert_node_equal)
(_Rb_tree::_M_reinsert_node_hint_unique)
(_Rb_tree::_M_reinsert_node_hint_equal, _Rb_tree::extract)
(_Rb_tree::_M_merge_unique, _Rb_tree::_M_merge_equal): Define.
(_Rb_tree_merge_helper): Specialize for multiset.
* include/bits/unordered_map.h (unordered_map): Declare
unordered_map<> and unordered_multimap<> as friends.
(unordered_map::node_type, unordered_map::insert_return_type)
(unordered_map::extract, unordered_map::merge)
(unordered_map::insert(node_type&&))
(unordered_map::insert(const_iterator, node_type&&))
(unordered_multimap): Declare _Hash_merge_helper as friend.
(unordered_multimap::node_type, unordered_multimap::extract)
(unordered_multimap::merge, unordered_multimap::insert(node_type&&))
(unordered_multimap::insert(const_iterator, node_type&&)): Define.
(_Hash_merge_helper): Specialize for unordered maps and multimaps.
* include/bits/unordered_set.h (unordered_set, unordered_multiset):
Declare _Hash_merge_helper as friend.
(unordered_set::node_type, unordered_set::insert_return_type)
(unordered_set::extract, unordered_set::merge)
(unordered_set::insert(node_type&&))
(unordered_set::insert(const_iterator, node_type&&)): Define.
(unordered_multiset::node_type, unordered_multiset::extract)
(unordered_multiset::merge, unordered_multiset::insert(node_type&&))
(unordered_multiset::insert(const_iterator, node_type&&)): Define.
(_Hash_merge_helper): Specialize for unordered sets and multisets.
* include/debug/map.h (map): Add using declarations or forwarding
functions for new members.
* include/debug/map.h (multimap): Likewise.
* include/debug/map.h (multiset): Likewise.
* include/debug/map.h (set): Likewise.
* include/debug/unordered_map (unordered_map, unordered_multimap):
Likewise.
* include/debug/unordered_set( unordered_set, unordered_multiset):
Likewise.
* python/libstdcxx/v6/printers.py (get_value_from_aligned_membuf): New
helper function.
(get_value_from_list_node, get_value_from_Rb_tree_node): Use helper.
(StdNodeHandlePrinter): Define printer for node handles.
(build_libstdcxx_dictionary): Register StdNodeHandlePrinter.
* testsuite/23_containers/map/modifiers/extract.cc: New.
* testsuite/23_containers/map/modifiers/merge.cc: New.
* testsuite/23_containers/multimap/modifiers/extract.cc: New.
* testsuite/23_containers/multimap/modifiers/merge.cc: New.
* testsuite/23_containers/multiset/modifiers/extract.cc: New.
* testsuite/23_containers/multiset/modifiers/merge.cc: New.
* testsuite/23_containers/set/modifiers/extract.cc: New.
* testsuite/23_containers/set/modifiers/merge.cc: New.
* testsuite/23_containers/unordered_map/modifiers/extract.cc: New.
* testsuite/23_containers/unordered_map/modifiers/merge.cc: New.
* testsuite/23_containers/unordered_multimap/modifiers/extract.cc:
New.
* testsuite/23_containers/unordered_multimap/modifiers/merge.cc: New.
* testsuite/23_containers/unordered_multiset/modifiers/extract.cc:
New.
* testsuite/23_containers/unordered_multiset/modifiers/merge.cc: New.
* testsuite/23_containers/unordered_set/modifiers/extract.cc: New.
* testsuite/23_containers/unordered_set/modifiers/merge.cc: New.
* testsuite/23_containers/unordered_set/instantiation_neg.cc: Adjust
dg-error lineno.
* testsuite/libstdc++-prettyprinters/cxx17.cc: Test node handles.
2016-09-22 Ville Voutilainen <ville.voutilainen@gmail.com>
Fix tests on old arm platforms for optional.

View File

@ -64,4 +64,4 @@
<code class="code">include/profile/impl/profiler_trace.h</code>. Use
<code class="code">__trace_vector_to_list</code> as an example.
</p><p>Add documentation in file <code class="code">doc/xml/manual/profile_mode.xml</code>.
</p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="profile_mode_impl.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="profile_mode.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="profile_mode_diagnostics.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Implementation Issues </td><td width="20%" align="center"><a accesskey="h" href="../index.html">Home</a></td><td width="40%" align="right" valign="top"> Diagnostics</td></tr></table></div></body></html>
</p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="profile_mode_impl.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="profile_mode.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="profile_mode_diagnostics.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Implementation Issues </td><td width="20%" align="center"><a accesskey="h" href="../index.html">Home</a></td><td width="40%" align="right" valign="top"> Diagnostics</td></tr></table></div></body></html>

View File

@ -666,11 +666,11 @@ Feature-testing recommendations for C++</a>.
</a>
</td><td align="center"> 6.1 </td><td align="left"><code class="code"> __cpp_lib_map_try_emplace &gt;= 201411</code>,
<code class="code"> __cpp_lib_unordered_map_try_emplace &gt;= 201411</code>
</td></tr><tr bgcolor="#C8B0B0"><td align="left"> Splicing Maps and Sets </td><td align="left">
</td></tr><tr><td align="left"> Splicing Maps and Sets </td><td align="left">
<a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0083r3.pdf" target="_top">
P0083R3
</a>
</td><td align="center"> No </td><td align="left"><code class="code"> __cpp_lib_node_extract &gt;= 201606 </code></td></tr><tr><td align="left">Non-member <code class="code">size()</code> and more</td><td align="left">
</td><td align="center"> 7 </td><td align="left"><code class="code"> __cpp_lib_node_extract &gt;= 201606 </code></td></tr><tr><td align="left">Non-member <code class="code">size()</code> and more</td><td align="left">
<a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4280.pdf" target="_top">
N4280
</a>

View File

@ -562,14 +562,13 @@ Feature-testing recommendations for C++</link>.
</row>
<row>
<?dbhtml bgcolor="#C8B0B0" ?>
<entry> Splicing Maps and Sets </entry>
<entry>
<link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0083r3.pdf">
P0083R3
</link>
</entry>
<entry align="center"> No </entry>
<entry align="center"> 7 </entry>
<entry><code> __cpp_lib_node_extract >= 201606 </code></entry>
</row>

View File

@ -129,7 +129,7 @@ bits_headers = \
${bits_srcdir}/specfun.h \
${bits_srcdir}/memoryfwd.h \
${bits_srcdir}/move.h \
${bits_srcdir}/std_mutex.h \
${bits_srcdir}/node_handle.h \
${bits_srcdir}/ostream.tcc \
${bits_srcdir}/ostream_insert.h \
${bits_srcdir}/parse_numbers.h \
@ -159,6 +159,7 @@ bits_headers = \
${bits_srcdir}/shared_ptr_base.h \
${bits_srcdir}/slice_array.h \
${bits_srcdir}/sstream.tcc \
${bits_srcdir}/std_mutex.h \
${bits_srcdir}/stl_algo.h \
${bits_srcdir}/stl_algobase.h \
${bits_srcdir}/stl_bvector.h \

View File

@ -419,7 +419,7 @@ bits_headers = \
${bits_srcdir}/specfun.h \
${bits_srcdir}/memoryfwd.h \
${bits_srcdir}/move.h \
${bits_srcdir}/std_mutex.h \
${bits_srcdir}/node_handle.h \
${bits_srcdir}/ostream.tcc \
${bits_srcdir}/ostream_insert.h \
${bits_srcdir}/parse_numbers.h \
@ -449,6 +449,7 @@ bits_headers = \
${bits_srcdir}/shared_ptr_base.h \
${bits_srcdir}/slice_array.h \
${bits_srcdir}/sstream.tcc \
${bits_srcdir}/std_mutex.h \
${bits_srcdir}/stl_algo.h \
${bits_srcdir}/stl_algobase.h \
${bits_srcdir}/stl_bvector.h \

View File

@ -33,6 +33,9 @@
#pragma GCC system_header
#include <bits/hashtable_policy.h>
#if __cplusplus > 201402L
# include <bits/node_handle.h>
#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
@ -308,6 +311,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using const_local_iterator = typename __hashtable_base::
const_local_iterator;
#if __cplusplus > 201402L
using node_type = _Node_handle<_Key, _Value, __node_alloc_type>;
using insert_return_type = _Node_insert_return<iterator, node_type>;
#endif
private:
__bucket_type* _M_buckets = &_M_single_bucket;
size_type _M_bucket_count = 1;
@ -762,6 +770,135 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// DR 1189.
// reserve, if present, comes from _Rehash_base.
#if __cplusplus > 201402L
/// Re-insert an extracted node into a container with unique keys.
insert_return_type
_M_reinsert_node(node_type&& __nh)
{
insert_return_type __ret;
if (__nh.empty())
__ret.position = end();
else
{
__glibcxx_assert(get_allocator() == __nh.get_allocator());
const key_type& __k = __nh._M_key();
__hash_code __code = this->_M_hash_code(__k);
size_type __bkt = _M_bucket_index(__k, __code);
if (__node_type* __n = _M_find_node(__bkt, __k, __code))
{
__ret.node = std::move(__nh);
__ret.position = iterator(__n);
__ret.inserted = false;
}
else
{
__ret.position
= _M_insert_unique_node(__bkt, __code, __nh._M_ptr);
__nh._M_ptr = nullptr;
__ret.inserted = true;
}
}
return __ret;
}
/// Re-insert an extracted node into a container with equivalent keys.
iterator
_M_reinsert_node_multi(const_iterator __hint, node_type&& __nh)
{
iterator __ret;
if (__nh.empty())
__ret = end();
else
{
__glibcxx_assert(get_allocator() == __nh.get_allocator());
auto __code = this->_M_hash_code(__nh._M_key());
auto __node = std::exchange(__nh._M_ptr, nullptr);
// FIXME: this deallocates the node on exception.
__ret = _M_insert_multi_node(__hint._M_cur, __code, __node);
}
return __ret;
}
/// Extract a node.
node_type
extract(const_iterator __pos)
{
__node_type* __n = __pos._M_cur;
size_t __bkt = _M_bucket_index(__n);
// Look for previous node to unlink it from the erased one, this
// is why we need buckets to contain the before begin to make
// this search fast.
__node_base* __prev_n = _M_get_previous_node(__bkt, __n);
if (__prev_n == _M_buckets[__bkt])
_M_remove_bucket_begin(__bkt, __n->_M_next(),
__n->_M_nxt ? _M_bucket_index(__n->_M_next()) : 0);
else if (__n->_M_nxt)
{
size_type __next_bkt = _M_bucket_index(__n->_M_next());
if (__next_bkt != __bkt)
_M_buckets[__next_bkt] = __prev_n;
}
__prev_n->_M_nxt = __n->_M_nxt;
__n->_M_nxt = nullptr;
--_M_element_count;
return { __n, this->_M_node_allocator() };
}
/// Extract a node.
node_type
extract(const _Key& __k)
{
node_type __nh;
auto __pos = find(__k);
if (__pos != end())
__nh = extract(const_iterator(__pos));
return __nh;
}
/// Merge from a compatible container into one with unique keys.
template<typename _Compatible_Hashtable>
void
_M_merge_unique(_Compatible_Hashtable& __src) noexcept
{
static_assert(is_same_v<typename _Compatible_Hashtable::node_type,
node_type>, "Node types are compatible");
__glibcxx_assert(get_allocator() == __src.get_allocator());
for (auto __i = __src.begin(), __end = __src.end(); __i != __end;)
{
auto __pos = __i++;
const key_type& __k = this->_M_extract()(__pos._M_cur->_M_v());
__hash_code __code = this->_M_hash_code(__k);
size_type __bkt = _M_bucket_index(__k, __code);
if (_M_find_node(__bkt, __k, __code) == nullptr)
{
auto __nh = __src.extract(__pos);
_M_insert_unique_node(__bkt, __code, __nh._M_ptr);
__nh._M_ptr = nullptr;
}
}
}
/// Merge from a compatible container into one with equivalent keys.
template<typename _Compatible_Hashtable>
void
_M_merge_multi(_Compatible_Hashtable& __src) noexcept
{
static_assert(is_same_v<typename _Compatible_Hashtable::node_type,
node_type>, "Node types are compatible");
__glibcxx_assert(get_allocator() == __src.get_allocator());
this->reserve(size() + __src.size());
for (auto __i = __src.begin(), __end = __src.end(); __i != __end;)
_M_reinsert_node_multi(cend(), __src.extract(__i++));
}
#endif // C++17
private:
// Helper rehash method used when keys are unique.
void _M_rehash_aux(size_type __n, std::true_type);
@ -2078,6 +2215,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_buckets = __new_buckets;
}
#if __cplusplus > 201402L
template<typename, typename, typename> class _Hash_merge_helper { };
#endif // C++17
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std

View File

@ -0,0 +1,330 @@
// Node handles for containers -*- C++ -*-
// Copyright (C) 2016 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.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
/** @file bits/node_handle.h
* This is an internal header file, included by other library headers.
* Do not attempt to use it directly.
* @headername{map,set,unordered_map,unordered_set}
*/
#ifndef _NODE_HANDLE
#define _NODE_HANDLE 1
#pragma GCC system_header
#if __cplusplus > 201402L
# define __cpp_lib_node_extract 201606
#include <optional>
#include <tuple>
#include <bits/alloc_traits.h>
#include <bits/ptr_traits.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Base class for node handle types of maps and sets.
template<typename _Val, typename _NodeAlloc>
class _Node_handle_common
{
using _AllocTraits = allocator_traits<_NodeAlloc>;
public:
using allocator_type = __alloc_rebind<_NodeAlloc, _Val>;
allocator_type
get_allocator() const noexcept
{
__glibcxx_assert(!this->empty());
return allocator_type(*_M_alloc);
}
explicit operator bool() const noexcept { return _M_ptr != nullptr; }
bool empty() const noexcept { return _M_ptr == nullptr; }
protected:
constexpr _Node_handle_common() noexcept : _M_ptr(), _M_alloc() {}
~_Node_handle_common() { _M_destroy(); }
_Node_handle_common(_Node_handle_common&& __nh) noexcept
: _M_ptr(__nh._M_ptr), _M_alloc(std::move(__nh._M_alloc))
{
__nh._M_ptr = nullptr;
__nh._M_alloc = nullopt;
}
_Node_handle_common&
operator=(_Node_handle_common&& __nh) noexcept
{
_M_destroy();
_M_ptr = __nh._M_ptr;
if constexpr (is_move_assignable_v<_NodeAlloc>)
{
if (_AllocTraits::propagate_on_container_move_assignment::value
|| !this->_M_alloc)
this->_M_alloc = std::move(__nh._M_alloc);
else
__glibcxx_assert(this->_M_alloc == __nh._M_alloc);
}
else
__glibcxx_assert(_M_alloc);
__nh._M_ptr = nullptr;
__nh._M_alloc = nullopt;
return *this;
}
_Node_handle_common(typename _AllocTraits::pointer __ptr,
const _NodeAlloc& __alloc)
: _M_ptr(__ptr), _M_alloc(__alloc) { }
void
_M_swap(_Node_handle_common& __nh) noexcept
{
using std::swap;
swap(_M_ptr, __nh._M_ptr);
if (_AllocTraits::propagate_on_container_swap
|| !_M_alloc || !__nh._M_alloc)
_M_alloc.swap(__nh._M_alloc);
else
__glibcxx_assert(_M_alloc == __nh._M_alloc);
}
private:
void
_M_destroy() noexcept
{
if (_M_ptr != nullptr)
{
allocator_type __alloc(*_M_alloc);
allocator_traits<allocator_type>::destroy(__alloc,
_M_ptr->_M_valptr());
_AllocTraits::deallocate(*_M_alloc, _M_ptr, 1);
}
}
protected:
typename _AllocTraits::pointer _M_ptr;
private:
optional<_NodeAlloc> _M_alloc;
template<typename _Key2, typename _Value2, typename _KeyOfValue,
typename _Compare, typename _ValueAlloc>
friend class _Rb_tree;
};
/// Node handle type for maps.
template<typename _Key, typename _Value, typename _NodeAlloc>
class _Node_handle : public _Node_handle_common<_Value, _NodeAlloc>
{
public:
constexpr _Node_handle() noexcept = default;
~_Node_handle() = default;
_Node_handle(_Node_handle&&) noexcept = default;
_Node_handle&
operator=(_Node_handle&&) noexcept = default;
using key_type = _Key;
using mapped_type = typename _Value::second_type;
key_type&
key() const noexcept
{
__glibcxx_assert(!this->empty());
return *_M_pkey;
}
mapped_type&
mapped() const noexcept
{
__glibcxx_assert(!this->empty());
return *_M_pmapped;
}
void
swap(_Node_handle& __nh) noexcept
{
this->_M_swap(__nh);
using std::swap;
swap(_M_pkey, __nh._M_pkey);
swap(_M_pmapped, __nh._M_pmapped);
}
friend void
swap(_Node_handle& __x, _Node_handle& __y)
noexcept(noexcept(__x.swap(__y)))
{ __x.swap(__y); }
private:
using _AllocTraits = allocator_traits<_NodeAlloc>;
using _PtrTraits = pointer_traits<typename _NodeAlloc::pointer>;
_Node_handle(typename _AllocTraits::pointer __ptr,
const _NodeAlloc& __alloc)
: _Node_handle_common<_Value, _NodeAlloc>(__ptr, __alloc)
{
if (__ptr)
{
auto& __key = const_cast<_Key&>(__ptr->_M_valptr()->first);
_M_pkey = _S_pointer_to(__key);
_M_pmapped = _S_pointer_to(__ptr->_M_valptr()->second);
}
else
{
_M_pkey = nullptr;
_M_pmapped = nullptr;
}
}
template<typename _Tp>
using __pointer = __ptr_rebind<typename _AllocTraits::pointer, _Tp>;
__pointer<_Key> _M_pkey = nullptr;
__pointer<typename _Value::second_type> _M_pmapped = nullptr;
template<typename _Tp>
__pointer<_Tp>
_S_pointer_to(_Tp& __obj)
{ return pointer_traits<__pointer<_Tp>>::pointer_to(__obj); }
const key_type&
_M_key() const noexcept { return key(); }
template<typename _Key2, typename _Value2, typename _KeyOfValue,
typename _Compare, typename _ValueAlloc>
friend class _Rb_tree;
template<typename _Key2, typename _Value2, typename _ValueAlloc,
typename _ExtractKey, typename _Equal,
typename _H1, typename _H2, typename _Hash,
typename _RehashPolicy, typename _Traits>
friend class _Hashtable;
};
/// Node handle type for sets.
template<typename _Value, typename _NodeAlloc>
class _Node_handle<_Value, _Value, _NodeAlloc>
: public _Node_handle_common<_Value, _NodeAlloc>
{
public:
constexpr _Node_handle() noexcept = default;
~_Node_handle() = default;
_Node_handle(_Node_handle&&) noexcept = default;
_Node_handle&
operator=(_Node_handle&&) noexcept = default;
using value_type = _Value;
value_type&
value() const noexcept
{
__glibcxx_assert(!this->empty());
return *this->_M_ptr->_M_valptr();
}
void
swap(_Node_handle& __nh) noexcept
{ this->_M_swap(__nh); }
friend void
swap(_Node_handle& __x, _Node_handle& __y)
noexcept(noexcept(__x.swap(__y)))
{ __x.swap(__y); }
private:
using _AllocTraits = allocator_traits<_NodeAlloc>;
_Node_handle(typename _AllocTraits::pointer __ptr,
const _NodeAlloc& __alloc)
: _Node_handle_common<_Value, _NodeAlloc>(__ptr, __alloc) { }
const value_type&
_M_key() const noexcept { return value(); }
template<typename _Key, typename _Val, typename _KeyOfValue,
typename _Compare, typename _Alloc>
friend class _Rb_tree;
template<typename _Key2, typename _Value2, typename _ValueAlloc,
typename _ExtractKey, typename _Equal,
typename _H1, typename _H2, typename _Hash,
typename _RehashPolicy, typename _Traits>
friend class _Hashtable;
};
/// Return type of insert(node_handle&&) on unique maps/sets.
template<typename _Iterator, typename _NodeHandle>
struct _Node_insert_return
{
bool inserted = false;
_Iterator position = _Iterator();
_NodeHandle node;
template<size_t _Idx>
decltype(auto) get() &
{ return std::get<_Idx>(std::tie(inserted, position, node)); }
template<size_t _Idx>
decltype(auto) get() const &
{ return std::get<_Idx>(std::tie(inserted, position, node)); }
template<size_t _Idx>
decltype(auto) get() &&
{
return std::move(std::get<_Idx>(std::tie(inserted, position, node)));
}
template<size_t _Idx>
decltype(auto) get() const &&
{
return std::move(std::get<_Idx>(std::tie(inserted, position, node)));
}
};
template<typename _Iterator, typename _NodeHandle>
struct tuple_size<_Node_insert_return<_Iterator, _NodeHandle>>
: integral_constant<size_t, 3> { };
template<typename _Iterator, typename _NodeHandle>
struct tuple_element<0, _Node_insert_return<_Iterator, _NodeHandle>>
{ using type = bool; };
template<typename _Iterator, typename _NodeHandle>
struct tuple_element<1, _Node_insert_return<_Iterator, _NodeHandle>>
{ using type = _Iterator; };
template<typename _Iterator, typename _NodeHandle>
struct tuple_element<2, _Node_insert_return<_Iterator, _NodeHandle>>
{ using type = _NodeHandle; };
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++17
#endif

View File

@ -67,6 +67,9 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
class multimap;
/**
* @brief A standard container made up of (key,value) pairs, which can be
* retrieved based on a key, in logarithmic time.
@ -153,6 +156,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef typename _Rep_type::reverse_iterator reverse_iterator;
typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator;
#if __cplusplus > 201402L
using node_type = typename _Rep_type::node_type;
using insert_return_type = typename _Rep_type::insert_return_type;
#endif
// [23.3.1.1] construct/copy/destroy
// (get_allocator() is also listed in this section)
@ -593,6 +601,57 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
#endif
#if __cplusplus > 201402L
/// Extract a node.
node_type
extract(const_iterator __pos)
{ return _M_t.extract(__pos); }
/// Extract a node.
node_type
extract(const key_type& __x)
{ return _M_t.extract(__x); }
/// Re-insert an extracted node.
insert_return_type
insert(node_type&& __nh)
{ return _M_t._M_reinsert_node_unique(std::move(__nh)); }
/// Re-insert an extracted node.
iterator
insert(const_iterator __hint, node_type&& __nh)
{ return _M_t._M_reinsert_node_hint_unique(__hint, std::move(__nh)); }
template<typename, typename>
friend class _Rb_tree_merge_helper;
template<typename _C2>
void
merge(map<_Key, _Tp, _C2, _Alloc>& __source)
{
using _Merge_helper = _Rb_tree_merge_helper<map, _C2>;
_M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source));
}
template<typename _C2>
void
merge(map<_Key, _Tp, _C2, _Alloc>&& __source)
{ merge(__source); }
template<typename _C2>
void
merge(multimap<_Key, _Tp, _C2, _Alloc>& __source)
{
using _Merge_helper = _Rb_tree_merge_helper<map, _C2>;
_M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source));
}
template<typename _C2>
void
merge(multimap<_Key, _Tp, _C2, _Alloc>&& __source)
{ merge(__source); }
#endif // C++17
#if __cplusplus > 201402L
#define __cpp_lib_map_try_emplace 201411
/**
@ -1365,6 +1424,30 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ __x.swap(__y); }
_GLIBCXX_END_NAMESPACE_CONTAINER
#if __cplusplus > 201402L
_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Allow std::map access to internals of compatible maps.
template<typename _Key, typename _Val, typename _Cmp1, typename _Alloc,
typename _Cmp2>
struct
_Rb_tree_merge_helper<_GLIBCXX_STD_C::map<_Key, _Val, _Cmp1, _Alloc>,
_Cmp2>
{
private:
friend class _GLIBCXX_STD_C::map<_Key, _Val, _Cmp1, _Alloc>;
static auto&
_S_get_tree(_GLIBCXX_STD_C::map<_Key, _Val, _Cmp2, _Alloc>& __map)
{ return __map._M_t; }
static auto&
_S_get_tree(_GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp2, _Alloc>& __map)
{ return __map._M_t; }
};
_GLIBCXX_END_NAMESPACE_VERSION
#endif // C++17
} // namespace std
#endif /* _STL_MAP_H */

View File

@ -65,6 +65,9 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
class map;
/**
* @brief A standard container made up of (key,value) pairs, which can be
* retrieved based on a key, in logarithmic time.
@ -151,6 +154,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef typename _Rep_type::reverse_iterator reverse_iterator;
typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator;
#if __cplusplus > 201402L
using node_type = typename _Rep_type::node_type;
#endif
// [23.3.2] construct/copy/destroy
// (get_allocator() is also listed in this section)
@ -595,6 +602,57 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ this->insert(__l.begin(), __l.end()); }
#endif
#if __cplusplus > 201402L
/// Extract a node.
node_type
extract(const_iterator __pos)
{ return _M_t.extract(__pos); }
/// Extract a node.
node_type
extract(const key_type& __x)
{ return _M_t.extract(__x); }
/// Re-insert an extracted node.
iterator
insert(node_type&& __nh)
{ return _M_t._M_reinsert_node_equal(std::move(__nh)); }
/// Re-insert an extracted node.
iterator
insert(const_iterator __hint, node_type&& __nh)
{ return _M_t._M_reinsert_node_hint_equal(__hint, std::move(__nh)); }
template<typename, typename>
friend class _Rb_tree_merge_helper;
template<typename _C2>
void
merge(multimap<_Key, _Tp, _C2, _Alloc>& __source)
{
using _Merge_helper = _Rb_tree_merge_helper<multimap, _C2>;
_M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source));
}
template<typename _C2>
void
merge(multimap<_Key, _Tp, _C2, _Alloc>&& __source)
{ merge(__source); }
template<typename _C2>
void
merge(map<_Key, _Tp, _C2, _Alloc>& __source)
{
using _Merge_helper = _Rb_tree_merge_helper<multimap, _C2>;
_M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source));
}
template<typename _C2>
void
merge(map<_Key, _Tp, _C2, _Alloc>&& __source)
{ merge(__source); }
#endif // C++17
#if __cplusplus >= 201103L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 130. Associative erase should return an iterator.
@ -1030,6 +1088,30 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ __x.swap(__y); }
_GLIBCXX_END_NAMESPACE_CONTAINER
#if __cplusplus > 201402L
_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Allow std::multimap access to internals of compatible maps.
template<typename _Key, typename _Val, typename _Cmp1, typename _Alloc,
typename _Cmp2>
struct
_Rb_tree_merge_helper<_GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp1, _Alloc>,
_Cmp2>
{
private:
friend class _GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp1, _Alloc>;
static auto&
_S_get_tree(_GLIBCXX_STD_C::map<_Key, _Val, _Cmp2, _Alloc>& __map)
{ return __map._M_t; }
static auto&
_S_get_tree(_GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp2, _Alloc>& __map)
{ return __map._M_t; }
};
_GLIBCXX_END_NAMESPACE_VERSION
#endif // C++17
} // namespace std
#endif /* _STL_MULTIMAP_H */

View File

@ -65,6 +65,9 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Key, typename _Compare, typename _Alloc>
class set;
/**
* @brief A standard container made up of elements, which can be retrieved
* in logarithmic time.
@ -133,6 +136,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef typename _Rep_type::size_type size_type;
typedef typename _Rep_type::difference_type difference_type;
#if __cplusplus > 201402L
using node_type = typename _Rep_type::node_type;
#endif
// allocation/deallocation
/**
* @brief Default constructor creates no elements.
@ -538,6 +545,57 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ this->insert(__l.begin(), __l.end()); }
#endif
#if __cplusplus > 201402L
/// Extract a node.
node_type
extract(const_iterator __pos)
{ return _M_t.extract(__pos); }
/// Extract a node.
node_type
extract(const key_type& __x)
{ return _M_t.extract(__x); }
/// Re-insert an extracted node.
iterator
insert(node_type&& __nh)
{ return _M_t._M_reinsert_node_equal(std::move(__nh)); }
/// Re-insert an extracted node.
iterator
insert(const_iterator __hint, node_type&& __nh)
{ return _M_t._M_reinsert_node_hint_equal(__hint, std::move(__nh)); }
template<typename, typename>
friend class _Rb_tree_merge_helper;
template<typename _Compare1>
void
merge(multiset<_Key, _Compare1, _Alloc>& __source)
{
using _Merge_helper = _Rb_tree_merge_helper<multiset, _Compare1>;
_M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source));
}
template<typename _Compare1>
void
merge(multiset<_Key, _Compare1, _Alloc>&& __source)
{ merge(__source); }
template<typename _Compare1>
void
merge(set<_Key, _Compare1, _Alloc>& __source)
{
using _Merge_helper = _Rb_tree_merge_helper<multiset, _Compare1>;
_M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source));
}
template<typename _Compare1>
void
merge(set<_Key, _Compare1, _Alloc>&& __source)
{ merge(__source); }
#endif // C++17
#if __cplusplus >= 201103L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 130. Associative erase should return an iterator.
@ -881,6 +939,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ __x.swap(__y); }
_GLIBCXX_END_NAMESPACE_CONTAINER
#if __cplusplus > 201402L
_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Allow std::multiset access to internals of compatible sets.
template<typename _Val, typename _Cmp1, typename _Alloc, typename _Cmp2>
struct
_Rb_tree_merge_helper<_GLIBCXX_STD_C::multiset<_Val, _Cmp1, _Alloc>,
_Cmp2>
{
private:
friend class _GLIBCXX_STD_C::multiset<_Val, _Cmp1, _Alloc>;
static auto&
_S_get_tree(_GLIBCXX_STD_C::set<_Val, _Cmp2, _Alloc>& __set)
{ return __set._M_t; }
static auto&
_S_get_tree(_GLIBCXX_STD_C::multiset<_Val, _Cmp2, _Alloc>& __set)
{ return __set._M_t; }
};
_GLIBCXX_END_NAMESPACE_VERSION
#endif // C++17
} // namespace std
#endif /* _STL_MULTISET_H */

View File

@ -65,6 +65,9 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Key, typename _Compare, typename _Alloc>
class multiset;
/**
* @brief A standard container made up of unique keys, which can be
* retrieved in logarithmic time.
@ -135,6 +138,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef typename _Rep_type::difference_type difference_type;
//@}
#if __cplusplus > 201402L
using node_type = typename _Rep_type::node_type;
using insert_return_type = typename _Rep_type::insert_return_type;
#endif
// allocation/deallocation
/**
* @brief Default constructor creates no elements.
@ -553,6 +561,57 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ this->insert(__l.begin(), __l.end()); }
#endif
#if __cplusplus > 201402L
/// Extract a node.
node_type
extract(const_iterator __pos)
{ return _M_t.extract(__pos); }
/// Extract a node.
node_type
extract(const key_type& __x)
{ return _M_t.extract(__x); }
/// Re-insert an extracted node.
insert_return_type
insert(node_type&& __nh)
{ return _M_t._M_reinsert_node_unique(std::move(__nh)); }
/// Re-insert an extracted node.
iterator
insert(const_iterator __hint, node_type&& __nh)
{ return _M_t._M_reinsert_node_hint_unique(__hint, std::move(__nh)); }
template<typename, typename>
friend class _Rb_tree_merge_helper;
template<typename _Compare1>
void
merge(set<_Key, _Compare1, _Alloc>& __source)
{
using _Merge_helper = _Rb_tree_merge_helper<set, _Compare1>;
_M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source));
}
template<typename _Compare1>
void
merge(set<_Key, _Compare1, _Alloc>&& __source)
{ merge(__source); }
template<typename _Compare1>
void
merge(multiset<_Key, _Compare1, _Alloc>& __source)
{
using _Merge_helper = _Rb_tree_merge_helper<set, _Compare1>;
_M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source));
}
template<typename _Compare1>
void
merge(multiset<_Key, _Compare1, _Alloc>&& __source)
{ merge(__source); }
#endif // C++17
#if __cplusplus >= 201103L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 130. Associative erase should return an iterator.
@ -897,5 +956,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ __x.swap(__y); }
_GLIBCXX_END_NAMESPACE_CONTAINER
#if __cplusplus > 201402L
_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Allow std::set access to internals of compatible sets.
template<typename _Val, typename _Cmp1, typename _Alloc, typename _Cmp2>
struct
_Rb_tree_merge_helper<_GLIBCXX_STD_C::set<_Val, _Cmp1, _Alloc>, _Cmp2>
{
private:
friend class _GLIBCXX_STD_C::set<_Val, _Cmp1, _Alloc>;
static auto&
_S_get_tree(_GLIBCXX_STD_C::set<_Val, _Cmp2, _Alloc>& __set)
{ return __set._M_t; }
static auto&
_S_get_tree(_GLIBCXX_STD_C::multiset<_Val, _Cmp2, _Alloc>& __set)
{ return __set._M_t; }
};
_GLIBCXX_END_NAMESPACE_VERSION
#endif // C++17
} //namespace std
#endif /* _STL_SET_H */

View File

@ -66,7 +66,10 @@
#include <bits/cpp_type_traits.h>
#include <ext/alloc_traits.h>
#if __cplusplus >= 201103L
#include <ext/aligned_buffer.h>
# include <ext/aligned_buffer.h>
#endif
#if __cplusplus > 201402L
# include <bits/node_handle.h>
#endif
namespace std _GLIBCXX_VISIBILITY(default)
@ -356,6 +359,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ typedef void type; };
#endif
#if __cplusplus > 201402L
template<typename _Tree1, typename _Cmp2>
struct _Rb_tree_merge_helper { };
#endif
template<typename _Key, typename _Val, typename _KeyOfValue,
typename _Compare, typename _Alloc = allocator<_Val> >
class _Rb_tree
@ -735,6 +743,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
#if __cplusplus > 201402L
using node_type = _Node_handle<_Key, _Val, _Node_allocator>;
using insert_return_type = _Node_insert_return<iterator, node_type>;
#endif
pair<_Base_ptr, _Base_ptr>
_M_get_insert_unique_pos(const key_type& __k);
@ -1274,6 +1287,172 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
_M_move_assign(_Rb_tree&, std::false_type);
#endif
#if __cplusplus > 201402L
public:
/// Re-insert an extracted node.
insert_return_type
_M_reinsert_node_unique(node_type&& __nh)
{
insert_return_type __ret;
if (__nh.empty())
__ret.position = end();
else
{
__glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc);
auto __res = _M_get_insert_unique_pos(__nh._M_key());
if (__res.second)
{
__ret.position
= _M_insert_node(__res.first, __res.second, __nh._M_ptr);
__nh._M_ptr = nullptr;
__ret.inserted = true;
}
else
{
__ret.node = std::move(__nh);
__ret.position = iterator(__res.first);
__ret.inserted = false;
}
}
return __ret;
}
/// Re-insert an extracted node.
iterator
_M_reinsert_node_equal(node_type&& __nh)
{
iterator __ret;
if (__nh.empty())
__ret = end();
else
{
__glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc);
auto __res = _M_get_insert_equal_pos(__nh._M_key());
if (__res.second)
__ret = _M_insert_node(__res.first, __res.second, __nh._M_ptr);
else
__ret = _M_insert_equal_lower_node(__nh._M_ptr);
__nh._M_ptr = nullptr;
}
return __ret;
}
/// Re-insert an extracted node.
iterator
_M_reinsert_node_hint_unique(const_iterator __hint, node_type&& __nh)
{
iterator __ret;
if (__nh.empty())
__ret = end();
else
{
__glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc);
auto __res = _M_get_insert_hint_unique_pos(__hint, __nh._M_key());
if (__res.second)
{
__ret = _M_insert_node(__res.first, __res.second, __nh._M_ptr);
__nh._M_ptr = nullptr;
}
else
__ret = iterator(__res.first);
}
return __ret;
}
/// Re-insert an extracted node.
iterator
_M_reinsert_node_hint_equal(const_iterator __hint, node_type&& __nh)
{
iterator __ret;
if (__nh.empty())
__ret = end();
else
{
__glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc);
auto __res = _M_get_insert_hint_equal_pos(__hint, __nh._M_key());
if (__res.second)
__ret = _M_insert_node(__res.first, __res.second, __nh._M_ptr);
else
__ret = _M_insert_equal_lower_node(__nh._M_ptr);
__nh._M_ptr = nullptr;
}
return __ret;
}
/// Extract a node.
node_type
extract(const_iterator __pos)
{
auto __ptr = _Rb_tree_rebalance_for_erase(
__pos._M_const_cast()._M_node, _M_impl._M_header);
--_M_impl._M_node_count;
return { static_cast<_Link_type>(__ptr), _M_get_Node_allocator() };
}
/// Extract a node.
node_type
extract(const key_type& __k)
{
node_type __nh;
auto __pos = find(__k);
if (__pos != end())
__nh = extract(const_iterator(__pos));
return __nh;
}
template<typename _Compare2>
using _Compatible_tree
= _Rb_tree<_Key, _Val, _KeyOfValue, _Compare2, _Alloc>;
template<typename, typename>
friend class _Rb_tree_merge_helper;
/// Merge from a compatible container into one with unique keys.
template<typename _Compare2>
void
_M_merge_unique(_Compatible_tree<_Compare2>& __src) noexcept
{
using _Merge_helper = _Rb_tree_merge_helper<_Rb_tree, _Compare2>;
for (auto __i = __src.begin(), __end = __src.end(); __i != __end;)
{
auto __pos = __i++;
auto __res = _M_get_insert_unique_pos(_KeyOfValue()(*__pos));
if (__res.second)
{
auto& __src_impl = _Merge_helper::_S_get_impl(__src);
auto __ptr = _Rb_tree_rebalance_for_erase(
__pos._M_node, __src_impl._M_header);
--__src_impl._M_node_count;
_M_insert_node(__res.first, __res.second,
static_cast<_Link_type>(__ptr));
}
}
}
/// Merge from a compatible container into one with equivalent keys.
template<typename _Compare2>
void
_M_merge_equal(_Compatible_tree<_Compare2>& __src) noexcept
{
using _Merge_helper = _Rb_tree_merge_helper<_Rb_tree, _Compare2>;
for (auto __i = __src.begin(), __end = __src.end(); __i != __end;)
{
auto __pos = __i++;
auto __res = _M_get_insert_equal_pos(_KeyOfValue()(*__pos));
if (__res.second)
{
auto& __src_impl = _Merge_helper::_S_get_impl(__src);
auto __ptr = _Rb_tree_rebalance_for_erase(
__pos._M_node, __src_impl._M_header);
--__src_impl._M_node_count;
_M_insert_node(__res.first, __res.second,
static_cast<_Link_type>(__ptr));
}
}
}
#endif // C++17
};
template<typename _Key, typename _Val, typename _KeyOfValue,
@ -2390,6 +2569,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return true;
}
#if __cplusplus > 201402L
// Allow access to internals of compatible _Rb_tree specializations.
template<typename _Key, typename _Val, typename _Sel, typename _Cmp1,
typename _Alloc, typename _Cmp2>
struct _Rb_tree_merge_helper<_Rb_tree<_Key, _Val, _Sel, _Cmp1, _Alloc>,
_Cmp2>
{
private:
friend class _Rb_tree<_Key, _Val, _Sel, _Cmp1, _Alloc>;
static auto&
_S_get_impl(_Rb_tree<_Key, _Val, _Sel, _Cmp2, _Alloc>& __tree)
{ return __tree._M_impl; }
};
#endif // C++17
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace

View File

@ -68,6 +68,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
__detail::_Default_ranged_hash,
__detail::_Prime_rehash_policy, _Tr>;
template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
class unordered_multimap;
/**
* @brief A standard container composed of unique keys (containing
* at most one of each key value) that associates values of another type
@ -126,6 +129,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef typename _Hashtable::difference_type difference_type;
//@}
#if __cplusplus > 201402L
using node_type = typename _Hashtable::node_type;
using insert_return_type = typename _Hashtable::insert_return_type;
#endif
//construct/destroy/copy
/// Default constructor.
@ -409,8 +417,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
emplace_hint(const_iterator __pos, _Args&&... __args)
{ return _M_h.emplace_hint(__pos, std::forward<_Args>(__args)...); }
#if __cplusplus > 201402L
/// Extract a node.
node_type
extract(const_iterator __pos)
{ return _M_h.extract(__pos); }
/// Extract a node.
node_type
extract(const key_type& __key)
{ return _M_h.extract(__key); }
/// Re-insert an extracted node.
insert_return_type
insert(node_type&& __nh)
{ return _M_h._M_reinsert_node(std::move(__nh)); }
/// Re-insert an extracted node.
iterator
insert(const_iterator, node_type&& __nh)
{ return _M_h._M_reinsert_node(std::move(__nh)).position; }
#define __cpp_lib_unordered_map_try_emplace 201411
/**
* @brief Attempts to build and insert a std::pair into the
@ -524,7 +551,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
std::forward<_Args>(__args)...));
return __i;
}
#endif
#endif // C++17
//@{
/**
@ -817,6 +844,37 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
noexcept( noexcept(_M_h.swap(__x._M_h)) )
{ _M_h.swap(__x._M_h); }
#if __cplusplus > 201402L
template<typename, typename, typename>
friend class _Hash_merge_helper;
template<typename _H2, typename _P2>
void
merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>& __source)
{
using _Merge_helper = _Hash_merge_helper<unordered_map, _H2, _P2>;
_M_h._M_merge_unique(_Merge_helper::_S_get_table(__source));
}
template<typename _H2, typename _P2>
void
merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>&& __source)
{ merge(__source); }
template<typename _H2, typename _P2>
void
merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>& __source)
{
using _Merge_helper = _Hash_merge_helper<unordered_map, _H2, _P2>;
_M_h._M_merge_unique(_Merge_helper::_S_get_table(__source));
}
template<typename _H2, typename _P2>
void
merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>&& __source)
{ merge(__source); }
#endif // C++17
// observers.
/// Returns the hash functor object with which the %unordered_map was
@ -1052,8 +1110,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Key1, typename _Tp1, typename _Hash1, typename _Pred1,
typename _Alloc1>
friend bool
operator==(const unordered_map<_Key1, _Tp1, _Hash1, _Pred1, _Alloc1>&,
const unordered_map<_Key1, _Tp1, _Hash1, _Pred1, _Alloc1>&);
operator==(const unordered_map<_Key1, _Tp1, _Hash1, _Pred1, _Alloc1>&,
const unordered_map<_Key1, _Tp1, _Hash1, _Pred1, _Alloc1>&);
};
/**
@ -1114,6 +1172,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef typename _Hashtable::difference_type difference_type;
//@}
#if __cplusplus > 201402L
using node_type = typename _Hashtable::node_type;
#endif
//construct/destroy/copy
/// Default constructor.
@ -1468,6 +1530,28 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
insert(initializer_list<value_type> __l)
{ _M_h.insert(__l); }
#if __cplusplus > 201402L
/// Extract a node.
node_type
extract(const_iterator __pos)
{ return _M_h.extract(__pos); }
/// Extract a node.
node_type
extract(const key_type& __key)
{ return _M_h.extract(__key); }
/// Re-insert an extracted node.
iterator
insert(node_type&& __nh)
{ return _M_h._M_reinsert_node_multi(cend(), std::move(__nh)); }
/// Re-insert an extracted node.
iterator
insert(const_iterator __hint, node_type&& __nh)
{ return _M_h._M_reinsert_node_multi(__hint, std::move(__nh)); }
#endif // C++17
//@{
/**
* @brief Erases an element from an %unordered_multimap.
@ -1551,6 +1635,39 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
noexcept( noexcept(_M_h.swap(__x._M_h)) )
{ _M_h.swap(__x._M_h); }
#if __cplusplus > 201402L
template<typename, typename, typename>
friend class _Hash_merge_helper;
template<typename _H2, typename _P2>
void
merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>& __source)
{
using _Merge_helper
= _Hash_merge_helper<unordered_multimap, _H2, _P2>;
_M_h._M_merge_multi(_Merge_helper::_S_get_table(__source));
}
template<typename _H2, typename _P2>
void
merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>&& __source)
{ merge(__source); }
template<typename _H2, typename _P2>
void
merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>& __source)
{
using _Merge_helper
= _Hash_merge_helper<unordered_multimap, _H2, _P2>;
_M_h._M_merge_multi(_Merge_helper::_S_get_table(__source));
}
template<typename _H2, typename _P2>
void
merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>&& __source)
{ merge(__source); }
#endif // C++17
// observers.
/// Returns the hash functor object with which the %unordered_multimap
@ -1786,6 +1903,59 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ return !(__x == __y); }
_GLIBCXX_END_NAMESPACE_CONTAINER
#if __cplusplus > 201402L
_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Allow std::unordered_map access to internals of compatible maps.
template<typename _Key, typename _Val, typename _Hash1, typename _Eq1,
typename _Alloc, typename _Hash2, typename _Eq2>
struct _Hash_merge_helper<
_GLIBCXX_STD_C::unordered_map<_Key, _Val, _Hash1, _Eq1, _Alloc>,
_Hash2, _Eq2>
{
private:
template<typename... _Tp>
using unordered_map = _GLIBCXX_STD_C::unordered_map<_Tp...>;
template<typename... _Tp>
using unordered_multimap = _GLIBCXX_STD_C::unordered_multimap<_Tp...>;
friend unordered_map<_Key, _Val, _Hash1, _Eq1, _Alloc>;
static auto&
_S_get_table(unordered_map<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map)
{ return __map._M_h; }
static auto&
_S_get_table(unordered_multimap<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map)
{ return __map._M_h; }
};
// Allow std::unordered_multimap access to internals of compatible maps.
template<typename _Key, typename _Val, typename _Hash1, typename _Eq1,
typename _Alloc, typename _Hash2, typename _Eq2>
struct _Hash_merge_helper<
_GLIBCXX_STD_C::unordered_multimap<_Key, _Val, _Hash1, _Eq1, _Alloc>,
_Hash2, _Eq2>
{
private:
template<typename... _Tp>
using unordered_map = _GLIBCXX_STD_C::unordered_map<_Tp...>;
template<typename... _Tp>
using unordered_multimap = _GLIBCXX_STD_C::unordered_multimap<_Tp...>;
friend unordered_multimap<_Key, _Val, _Hash1, _Eq1, _Alloc>;
static auto&
_S_get_table(unordered_map<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map)
{ return __map._M_h; }
static auto&
_S_get_table(unordered_multimap<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map)
{ return __map._M_h; }
};
_GLIBCXX_END_NAMESPACE_VERSION
#endif // C++17
} // namespace std
#endif /* _UNORDERED_MAP_H */

View File

@ -65,6 +65,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
__detail::_Default_ranged_hash,
__detail::_Prime_rehash_policy, _Tr>;
template<class _Value, class _Hash, class _Pred, class _Alloc>
class unordered_multiset;
/**
* @brief A standard container composed of unique keys (containing
* at most one of each key value) in which the elements' keys are
@ -120,6 +123,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef typename _Hashtable::difference_type difference_type;
//@}
#if __cplusplus > 201402L
using node_type = typename _Hashtable::node_type;
using insert_return_type = typename _Hashtable::insert_return_type;
#endif
// construct/destroy/copy
/// Default constructor.
@ -470,6 +478,28 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
insert(initializer_list<value_type> __l)
{ _M_h.insert(__l); }
#if __cplusplus > 201402L
/// Extract a node.
node_type
extract(const_iterator __pos)
{ return _M_h.extract(__pos); }
/// Extract a node.
node_type
extract(const key_type& __key)
{ return _M_h.extract(__key); }
/// Re-insert an extracted node.
insert_return_type
insert(node_type&& __nh)
{ return _M_h._M_reinsert_node(std::move(__nh)); }
/// Re-insert an extracted node.
iterator
insert(const_iterator, node_type&& __nh)
{ return _M_h._M_reinsert_node(std::move(__nh)).position; }
#endif // C++17
//@{
/**
* @brief Erases an element from an %unordered_set.
@ -552,6 +582,37 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
noexcept( noexcept(_M_h.swap(__x._M_h)) )
{ _M_h.swap(__x._M_h); }
#if __cplusplus > 201402L
template<typename, typename, typename>
friend class _Hash_merge_helper;
template<typename _H2, typename _P2>
void
merge(unordered_set<_Value, _H2, _P2, _Alloc>& __source)
{
using _Merge_helper = _Hash_merge_helper<unordered_set, _H2, _P2>;
_M_h._M_merge_unique(_Merge_helper::_S_get_table(__source));
}
template<typename _H2, typename _P2>
void
merge(unordered_set<_Value, _H2, _P2, _Alloc>&& __source)
{ merge(__source); }
template<typename _H2, typename _P2>
void
merge(unordered_multiset<_Value, _H2, _P2, _Alloc>& __source)
{
using _Merge_helper = _Hash_merge_helper<unordered_set, _H2, _P2>;
_M_h._M_merge_unique(_Merge_helper::_S_get_table(__source));
}
template<typename _H2, typename _P2>
void
merge(unordered_multiset<_Value, _H2, _P2, _Alloc>&& __source)
{ merge(__source); }
#endif // C++17
// observers.
/// Returns the hash functor object with which the %unordered_set was
@ -793,6 +854,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef typename _Hashtable::difference_type difference_type;
//@}
#if __cplusplus > 201402L
using node_type = typename _Hashtable::node_type;
#endif
// construct/destroy/copy
/// Default constructor.
@ -1121,6 +1186,28 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
insert(initializer_list<value_type> __l)
{ _M_h.insert(__l); }
#if __cplusplus > 201402L
/// Extract a node.
node_type
extract(const_iterator __pos)
{ return _M_h.extract(__pos); }
/// Extract a node.
node_type
extract(const key_type& __key)
{ return _M_h.extract(__key); }
/// Re-insert an extracted node.
iterator
insert(node_type&& __nh)
{ return _M_h._M_reinsert_node_multi(cend(), std::move(__nh)); }
/// Re-insert an extracted node.
iterator
insert(const_iterator __hint, node_type&& __nh)
{ return _M_h._M_reinsert_node_multi(__hint, std::move(__nh)); }
#endif // C++17
//@{
/**
* @brief Erases an element from an %unordered_multiset.
@ -1208,6 +1295,39 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
noexcept( noexcept(_M_h.swap(__x._M_h)) )
{ _M_h.swap(__x._M_h); }
#if __cplusplus > 201402L
template<typename, typename, typename>
friend class _Hash_merge_helper;
template<typename _H2, typename _P2>
void
merge(unordered_multiset<_Value, _H2, _P2, _Alloc>& __source)
{
using _Merge_helper
= _Hash_merge_helper<unordered_multiset, _H2, _P2>;
_M_h._M_merge_multi(_Merge_helper::_S_get_table(__source));
}
template<typename _H2, typename _P2>
void
merge(unordered_multiset<_Value, _H2, _P2, _Alloc>&& __source)
{ merge(__source); }
template<typename _H2, typename _P2>
void
merge(unordered_set<_Value, _H2, _P2, _Alloc>& __source)
{
using _Merge_helper
= _Hash_merge_helper<unordered_multiset, _H2, _P2>;
_M_h._M_merge_multi(_Merge_helper::_S_get_table(__source));
}
template<typename _H2, typename _P2>
void
merge(unordered_set<_Value, _H2, _P2, _Alloc>&& __source)
{ merge(__source); }
#endif // C++17
// observers.
/// Returns the hash functor object with which the %unordered_multiset
@ -1429,6 +1549,58 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ return !(__x == __y); }
_GLIBCXX_END_NAMESPACE_CONTAINER
#if __cplusplus > 201402L
_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Allow std::unordered_set access to internals of compatible sets.
template<typename _Val, typename _Hash1, typename _Eq1, typename _Alloc,
typename _Hash2, typename _Eq2>
struct _Hash_merge_helper<
_GLIBCXX_STD_C::unordered_set<_Val, _Hash1, _Eq1, _Alloc>, _Hash2, _Eq2>
{
private:
template<typename... _Tp>
using unordered_set = _GLIBCXX_STD_C::unordered_set<_Tp...>;
template<typename... _Tp>
using unordered_multiset = _GLIBCXX_STD_C::unordered_multiset<_Tp...>;
friend unordered_set<_Val, _Hash1, _Eq1, _Alloc>;
static auto&
_S_get_table(unordered_set<_Val, _Hash2, _Eq2, _Alloc>& __set)
{ return __set._M_h; }
static auto&
_S_get_table(unordered_multiset<_Val, _Hash2, _Eq2, _Alloc>& __set)
{ return __set._M_h; }
};
// Allow std::unordered_multiset access to internals of compatible sets.
template<typename _Val, typename _Hash1, typename _Eq1, typename _Alloc,
typename _Hash2, typename _Eq2>
struct _Hash_merge_helper<
_GLIBCXX_STD_C::unordered_multiset<_Val, _Hash1, _Eq1, _Alloc>,
_Hash2, _Eq2>
{
private:
template<typename... _Tp>
using unordered_set = _GLIBCXX_STD_C::unordered_set<_Tp...>;
template<typename... _Tp>
using unordered_multiset = _GLIBCXX_STD_C::unordered_multiset<_Tp...>;
friend unordered_multiset<_Val, _Hash1, _Eq1, _Alloc>;
static auto&
_S_get_table(unordered_set<_Val, _Hash2, _Eq2, _Alloc>& __set)
{ return __set._M_h; }
static auto&
_S_get_table(unordered_multiset<_Val, _Hash2, _Eq2, _Alloc>& __set)
{ return __set._M_h; }
};
_GLIBCXX_END_NAMESPACE_VERSION
#endif // C++17
} // namespace std
#endif /* _UNORDERED_SET_H */

View File

@ -397,8 +397,52 @@ namespace __debug
std::forward<_Obj>(__obj)),
this);
}
#endif
#endif // C++17
#if __cplusplus > 201402L
using node_type = typename _Base::node_type;
struct insert_return_type
{
bool inserted;
iterator position;
node_type node;
};
node_type
extract(const_iterator __position)
{
__glibcxx_check_erase(__position);
this->_M_invalidate_if(_Equal(__position.base()));
return _Base::extract(__position.base());
}
node_type
extract(const key_type& __key)
{
const auto __position = find(__key);
if (__position != end())
return extract(__position);
return {};
}
insert_return_type
insert(node_type&& __nh)
{
auto __ret = _Base::insert(std::move(__nh));
iterator __pos = iterator(__ret.position, this);
return { __ret.inserted, __pos, std::move(__ret.node) };
}
iterator
insert(const_iterator __hint, node_type&& __nh)
{
__glibcxx_check_insert(__hint);
return iterator(_Base::insert(__hint.base(), std::move(__nh)), this);
}
using _Base::merge;
#endif // C++17
#if __cplusplus >= 201103L
iterator

View File

@ -296,6 +296,40 @@ namespace __debug
_Base::insert(__first, __last);
}
#if __cplusplus > 201402L
using node_type = typename _Base::node_type;
node_type
extract(const_iterator __position)
{
__glibcxx_check_erase(__position);
this->_M_invalidate_if(_Equal(__position.base()));
return _Base::extract(__position.base());
}
node_type
extract(const key_type& __key)
{
const auto __position = find(__key);
if (__position != end())
return extract(__position);
return {};
}
iterator
insert(node_type&& __nh)
{ return iterator(_Base::insert(std::move(__nh)), this); }
iterator
insert(const_iterator __hint, node_type&& __nh)
{
__glibcxx_check_insert(__hint);
return iterator(_Base::insert(__hint.base(), std::move(__nh)), this);
}
using _Base::merge;
#endif // C++17
#if __cplusplus >= 201103L
iterator
erase(const_iterator __position)

View File

@ -287,6 +287,40 @@ namespace __debug
{ _Base::insert(__l); }
#endif
#if __cplusplus > 201402L
using node_type = typename _Base::node_type;
node_type
extract(const_iterator __position)
{
__glibcxx_check_erase(__position);
this->_M_invalidate_if(_Equal(__position.base()));
return _Base::extract(__position.base());
}
node_type
extract(const key_type& __key)
{
const auto __position = find(__key);
if (__position != end())
return extract(__position);
return {};
}
iterator
insert(node_type&& __nh)
{ return iterator(_Base::insert(std::move(__nh)), this); }
iterator
insert(const_iterator __hint, node_type&& __nh)
{
__glibcxx_check_insert(__hint);
return iterator(_Base::insert(__hint.base(), std::move(__nh)), this);
}
using _Base::merge;
#endif // C++17
#if __cplusplus >= 201103L
iterator
erase(const_iterator __position)

View File

@ -296,6 +296,51 @@ namespace __debug
{ _Base::insert(__l); }
#endif
#if __cplusplus > 201402L
using node_type = typename _Base::node_type;
struct insert_return_type
{
bool inserted;
iterator position;
node_type node;
};
node_type
extract(const_iterator __position)
{
__glibcxx_check_erase(__position);
this->_M_invalidate_if(_Equal(__position.base()));
return _Base::extract(__position.base());
}
node_type
extract(const key_type& __key)
{
const auto __position = find(__key);
if (__position != end())
return extract(__position);
return {};
}
insert_return_type
insert(node_type&& __nh)
{
auto __ret = _Base::insert(std::move(__nh));
iterator __pos = iterator(__ret.position, this);
return { __ret.inserted, __pos, std::move(__ret.node) };
}
iterator
insert(const_iterator __hint, node_type&& __nh)
{
__glibcxx_check_insert(__hint);
return iterator(_Base::insert(__hint.base(), std::move(__nh)), this);
}
using _Base::merge;
#endif // C++17
#if __cplusplus >= 201103L
iterator
erase(const_iterator __position)

View File

@ -458,8 +458,59 @@ namespace __debug
std::forward<_Obj>(__obj)),
this);
}
#endif
#endif // C++17
#if __cplusplus > 201402L
using node_type = typename _Base::node_type;
struct insert_return_type
{
bool inserted;
iterator position;
node_type node;
};
node_type
extract(const_iterator __position)
{
__glibcxx_check_erase(__position);
_Base_const_iterator __victim = __position.base();
this->_M_invalidate_if(
[__victim](_Base_const_iterator __it) { return __it == __victim; }
);
this->_M_invalidate_local_if(
[__victim](_Base_const_local_iterator __it) {
return __it._M_curr() == __victim._M_cur;
});
return _Base::extract(__position.base());
}
node_type
extract(const key_type& __key)
{
const auto __position = find(__key);
if (__position != end())
return extract(__position);
return {};
}
insert_return_type
insert(node_type&& __nh)
{
auto __ret = _Base::insert(std::move(__nh));
iterator __pos = iterator(__ret.position, this);
return { __ret.inserted, __pos, std::move(__ret.node) };
}
iterator
insert(const_iterator __hint, node_type&& __nh)
{
__glibcxx_check_insert(__hint);
return iterator(_Base::insert(__hint.base(), std::move(__nh)), this);
}
using _Base::merge;
#endif // C++17
iterator
find(const key_type& __key)
@ -913,6 +964,47 @@ namespace __debug
_M_check_rehashed(__bucket_count);
}
#if __cplusplus > 201402L
using node_type = typename _Base::node_type;
node_type
extract(const_iterator __position)
{
__glibcxx_check_erase(__position);
_Base_const_iterator __victim = __position.base();
this->_M_invalidate_if(
[__victim](_Base_const_iterator __it) { return __it == __victim; }
);
this->_M_invalidate_local_if(
[__victim](_Base_const_local_iterator __it) {
return __it._M_curr() == __victim._M_cur;
});
return _Base::extract(__position.base());
}
node_type
extract(const key_type& __key)
{
const auto __position = find(__key);
if (__position != end())
return extract(__position);
return {};
}
iterator
insert(node_type&& __nh)
{ return iterator(_Base::insert(std::move(__nh)), this); }
iterator
insert(const_iterator __hint, node_type&& __nh)
{
__glibcxx_check_insert(__hint);
return iterator(_Base::insert(__hint.base(), std::move(__nh)), this);
}
using _Base::merge;
#endif // C++17
iterator
find(const key_type& __key)
{ return iterator(_Base::find(__key), this); }

View File

@ -370,6 +370,58 @@ namespace __debug
_M_check_rehashed(__bucket_count);
}
#if __cplusplus > 201402L
using node_type = typename _Base::node_type;
struct insert_return_type
{
bool inserted;
iterator position;
node_type node;
};
node_type
extract(const_iterator __position)
{
__glibcxx_check_erase(__position);
_Base_const_iterator __victim = __position.base();
this->_M_invalidate_if(
[__victim](_Base_const_iterator __it) { return __it == __victim; }
);
this->_M_invalidate_local_if(
[__victim](_Base_const_local_iterator __it) {
return __it._M_curr() == __victim._M_cur;
});
return _Base::extract(__position.base());
}
node_type
extract(const key_type& __key)
{
const auto __position = find(__key);
if (__position != end())
return extract(__position);
return {};
}
insert_return_type
insert(node_type&& __nh)
{
auto __ret = _Base::insert(std::move(__nh));
iterator __pos = iterator(__ret.position, this);
return { __ret.inserted, __pos, std::move(__ret.node) };
}
iterator
insert(const_iterator __hint, node_type&& __nh)
{
__glibcxx_check_insert(__hint);
return iterator(_Base::insert(__hint.base(), std::move(__nh)), this);
}
using _Base::merge;
#endif // C++17
iterator
find(const key_type& __key)
{ return iterator(_Base::find(__key), this); }
@ -821,6 +873,47 @@ namespace __debug
_M_check_rehashed(__bucket_count);
}
#if __cplusplus > 201402L
using node_type = typename _Base::node_type;
node_type
extract(const_iterator __position)
{
__glibcxx_check_erase(__position);
_Base_const_iterator __victim = __position.base();
this->_M_invalidate_if(
[__victim](_Base_const_iterator __it) { return __it == __victim; }
);
this->_M_invalidate_local_if(
[__victim](_Base_const_local_iterator __it) {
return __it._M_curr() == __victim._M_cur;
});
return _Base::extract(__position.base());
}
node_type
extract(const key_type& __key)
{
const auto __position = find(__key);
if (__position != end())
return extract(__position);
return {};
}
iterator
insert(node_type&& __nh)
{ return iterator(_Base::insert(std::move(__nh)), this); }
iterator
insert(const_iterator __hint, node_type&& __nh)
{
__glibcxx_check_insert(__hint);
return iterator(_Base::insert(__hint.base(), std::move(__nh)), this);
}
using _Base::merge;
#endif // C++17
iterator
find(const key_type& __key)
{ return iterator(_Base::find(__key), this); }

View File

@ -130,6 +130,10 @@ class UniquePointerPrinter:
return ('std::unique_ptr<%s> containing %s' % (str(v.type.target()),
str(v)))
def get_value_from_aligned_membuf(buf, valtype):
"""Returns the value held in a __gnu_cxx::__aligned_membuf."""
return buf['_M_storage'].address.cast(valtype.pointer()).dereference()
def get_value_from_list_node(node):
"""Returns the value held in an _List_node<_Val>"""
try:
@ -139,9 +143,8 @@ def get_value_from_list_node(node):
return node['_M_data']
elif member == '_M_storage':
# C++11 implementation, node stores value in __aligned_membuf
p = node['_M_storage']['_M_storage'].address
p = p.cast(node.type.template_argument(0).pointer())
return p.dereference()
valtype = node.type.template_argument(0)
return get_value_from_aligned_membuf(node['_M_storage'], valtype)
except:
pass
raise ValueError("Unsupported implementation for %s" % str(node.type))
@ -461,9 +464,8 @@ def get_value_from_Rb_tree_node(node):
return node['_M_value_field']
elif member == '_M_storage':
# C++11 implementation, node stores value in __aligned_membuf
p = node['_M_storage']['_M_storage'].address
p = p.cast(node.type.template_argument(0).pointer())
return p.dereference()
valtype = node.type.template_argument(0)
return get_value_from_aligned_membuf(node['_M_storage'], valtype)
except:
pass
raise ValueError("Unsupported implementation for %s" % str(node.type))
@ -1017,6 +1019,48 @@ class StdVariantPrinter(SingleObjContainerPrinter):
return "%s [index %d] containing %s" % (self.typename, self.index, self.visualizer.to_string())
return "%s [index %d]" % (self.typename, self.index)
class StdNodeHandlePrinter(SingleObjContainerPrinter):
"Print a container node handle"
def __init__(self, typename, val):
self.value_type = val.type.template_argument(1)
nodetype = val.type.template_argument(2).template_argument(0)
self.is_rb_tree_node = nodetype.name.startswith('std::_Rb_tree_node')
self.is_map_node = val.type.template_argument(0) != self.value_type
nodeptr = val['_M_ptr']
if nodeptr:
if self.is_rb_tree_node:
contained_value = get_value_from_Rb_tree_node(nodeptr.dereference())
else:
contained_value = get_value_from_aligned_membuf(nodeptr['_M_storage'],
self.value_type)
visualizer = gdb.default_visualizer(contained_value)
else:
contained_value = None
visualizer = None
optalloc = val['_M_alloc']
self.alloc = optalloc['_M_payload'] if optalloc['_M_engaged'] else None
super(StdNodeHandlePrinter, self).__init__(contained_value, visualizer,
'array')
def to_string(self):
desc = 'node handle for '
if not self.is_rb_tree_node:
desc += 'unordered '
if self.is_map_node:
desc += 'map';
else:
desc += 'set';
if self.contained_value:
desc += ' with element'
if hasattr(self.visualizer, 'children'):
return "%s = %s" % (desc, self.visualizer.to_string())
return desc
else:
return 'empty %s' % desc
class StdExpStringViewPrinter:
"Print a std::basic_string_view or std::experimental::basic_string_view"
@ -1491,6 +1535,8 @@ def build_libstdcxx_dictionary ():
'basic_string_view', StdExpStringViewPrinter)
libstdcxx_printer.add_version('std::',
'variant', StdVariantPrinter)
libstdcxx_printer.add_version('std::',
'_Node_handle', StdNodeHandlePrinter)
# Extensions.
libstdcxx_printer.add_version('__gnu_cxx::', 'slist', StdSlistPrinter)

View File

@ -0,0 +1,147 @@
// Copyright (C) 2016 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-options "-std=gnu++17" }
#include <map>
#include <algorithm>
#include <testsuite_hooks.h>
using test_type = std::map<int, int>;
void
test01()
{
bool test __attribute__((unused)) = true;
test_type c{ {1, 10}, {2, 20}, {3, 30} };
test_type::node_type node;
test_type::insert_return_type ins;
test_type::iterator pos;
node = c.extract(0);
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
ins = c.insert(std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
VERIFY( !ins.inserted );
VERIFY( !ins.node );
VERIFY( ins.position == c.end() );
node = c.extract(1);
VERIFY( (bool)node );
VERIFY( !node.empty() );
VERIFY( c.size() == 2 );
VERIFY( c.count(1) == 0 );
VERIFY( node.get_allocator() == c.get_allocator() );
VERIFY( node.key() == 1 );
VERIFY( node.mapped() == 10 );
node.key() = 4;
node.mapped() = 40;
VERIFY( node.key() == 4 );
VERIFY( node.mapped() == 40 );
ins = c.insert(std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
VERIFY( ins.inserted );
VERIFY( !ins.node );
VERIFY( ins.position != c.end() );
VERIFY( ins.position->first == 4 );
VERIFY( ins.position->second == 40 );
VERIFY( c.count(1) == 0 );
VERIFY( c.count(4) == 1 );
VERIFY( std::is_sorted(c.begin(), c.end()) );
pos = c.insert(c.begin(), std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
VERIFY( pos == c.end() );
node = c.extract(2);
pos = c.insert(c.begin(), std::move(node));
VERIFY( c.size() == 3 );
VERIFY( pos != c.end() );
VERIFY( pos->first == 2 );
VERIFY( pos->second == 20 );
test_type c2 = c;
node = c2.extract(3);
ins = c.insert(std::move(node));
VERIFY( node.empty() );
VERIFY( ins.position != c.end() );
VERIFY( !ins.inserted );
VERIFY( !ins.node.empty() );
VERIFY( ins.node.key() == 3 );
VERIFY( ins.node.mapped() == 30 );
VERIFY( ins.position->first == ins.node.key() );
}
void
test02()
{
bool test __attribute__((unused)) = true;
test_type c{ {1, 10}, {2, 20}, {3, 30} };
test_type::node_type node;
test_type::insert_return_type ins;
node = c.extract(c.begin());
VERIFY( (bool)node );
VERIFY( !node.empty() );
VERIFY( c.size() == 2 );
VERIFY( node.get_allocator() == c.get_allocator() );
VERIFY( node.key() == 1 );
VERIFY( node.mapped() == 10 );
ins = c.insert(std::move(node));
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
VERIFY( ins.inserted );
VERIFY( !ins.node );
VERIFY( ins.position != c.end() );
VERIFY( ins.position->first == 1 );
VERIFY( ins.position->second == 10 );
}
void
test03()
{
struct less : std::less<int> { };
using std::is_same_v;
using compat_type1 = std::map<int, int, less>;
static_assert( is_same_v<test_type::node_type, compat_type1::node_type> );
using compat_type2 = std::multimap<int, int>;
static_assert( is_same_v<test_type::node_type, compat_type2::node_type> );
using compat_type3 = std::multimap<int, int, less>;
static_assert( is_same_v<test_type::node_type, compat_type3::node_type> );
}
int
main()
{
test01();
test02();
test03();
}

View File

@ -0,0 +1,147 @@
// Copyright (C) 2016 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-options "-std=gnu++17" }
#include <map>
#include <algorithm>
#include <testsuite_hooks.h>
using test_type = std::map<int, int>;
void
test01()
{
bool test __attribute__((unused)) = true;
const test_type c0{ {1, 10}, {2, 20}, {3, 30} };
test_type c1 = c0, c2 = c0;
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( c2 == c0 );
c1.clear();
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
c2.merge(std::move(c1));
VERIFY( c1.empty() );
VERIFY( c2 == c0 );
}
void
test02()
{
bool test __attribute__((unused)) = true;
const test_type c0{ {1, 10}, {2, 20}, {3, 30} };
test_type c1 = c0;
std::map<int, int, std::less<>> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( std::equal(c2.begin(), c2.end(), c0.begin(), c0.end()) );
c1.clear();
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
c2.merge(std::move(c1));
VERIFY( c1.empty() );
VERIFY( std::equal(c2.begin(), c2.end(), c0.begin(), c0.end()) );
}
void
test03()
{
bool test __attribute__((unused)) = true;
const test_type c0{ {1, 10}, {2, 20}, {3, 30} };
test_type c1 = c0;
std::map<int, int, std::greater<>> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( std::equal(c2.rbegin(), c2.rend(), c0.begin(), c0.end()) );
c1.clear();
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
c2.merge(c1);
VERIFY( c1.empty() );
VERIFY( std::equal(c2.rbegin(), c2.rend(), c0.begin(), c0.end()) );
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
}
void
test04()
{
bool test __attribute__((unused)) = true;
const test_type c0{ {1, 10}, {2, 20}, {3, 30} };
test_type c1 = c0;
std::multimap<int, int, std::greater<>> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( std::equal(c2.rbegin(), c2.rend(), c0.begin(), c0.end()) );
c1.clear();
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
c2.merge(c1);
VERIFY( c1.empty() );
VERIFY( std::equal(c2.rbegin(), c2.rend(), c0.begin(), c0.end()) );
c1 = c0;
c2.merge(c1);
VERIFY( c1.empty() );
VERIFY( c2.size() == (2 * c0.size()) );
VERIFY( std::is_sorted(c2.begin(), c2.end(), c2.value_comp()) );
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( std::equal(c2.rbegin(), c2.rend(), c0.begin(), c0.end()) );
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( std::equal(c2.rbegin(), c2.rend(), c0.begin(), c0.end()) );
c1.clear();
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
}
int
main()
{
test01();
test02();
test03();
test04();
}

View File

@ -0,0 +1,141 @@
// Copyright (C) 2016 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-options "-std=gnu++17" }
#include <map>
#include <algorithm>
#include <testsuite_hooks.h>
using test_type = std::multimap<int, int>;
void
test01()
{
bool test __attribute__((unused)) = true;
test_type c{ {1, 10}, { 1, 11 }, {2, 20}, { 2, 21}, {3, 30}, { 3, 31 } };
test_type::node_type node;
test_type::iterator pos;
node = c.extract(0);
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
pos = c.insert(std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
VERIFY( pos == c.end() );
node = c.extract(1);
VERIFY( (bool)node );
VERIFY( !node.empty() );
VERIFY( c.size() == 5 );
VERIFY( c.count(1) == 1 );
VERIFY( node.get_allocator() == c.get_allocator() );
VERIFY( node.key() == 1 );
int mapped = node.mapped();
VERIFY( mapped == 10 || mapped == 11 );
node.key() = 4;
node.mapped() = 40;
VERIFY( node.key() == 4 );
VERIFY( node.mapped() == 40 );
pos = c.insert(std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
VERIFY( pos != c.end() );
VERIFY( pos->first == 4 );
VERIFY( pos->second == 40 );
VERIFY( c.count(1) == 1 );
VERIFY( c.count(4) == 1 );
VERIFY( std::is_sorted(c.begin(), c.end()) );
pos = c.insert(c.begin(), std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
VERIFY( pos == c.end() );
node = c.extract(1);
mapped = node.mapped();
pos = c.insert(c.begin(), std::move(node));
VERIFY( !node );
VERIFY( c.size() == 6 );
VERIFY( pos != c.end() );
VERIFY( pos->first == 1 );
VERIFY( pos->second == mapped );
test_type c2 = c;
node = c2.extract(1);
mapped = node.mapped();
pos = c.insert(std::move(node));
VERIFY( pos != c.end() );
VERIFY( node.empty() );
VERIFY( pos->first == 1 );
VERIFY( pos->second == mapped );
}
void
test02()
{
bool test __attribute__((unused)) = true;
test_type c{ {1, 10}, { 1, 11 }, {2, 20}, { 2, 21}, {3, 30}, { 3, 31 } };
test_type::node_type node;
test_type::iterator pos;
node = c.extract(c.begin());
VERIFY( !node.empty() );
VERIFY( c.size() == 5 );
VERIFY( node.get_allocator() == c.get_allocator() );
VERIFY( node.key() == 1 );
VERIFY( node.mapped() == 10 );
pos = c.insert(std::next(c.begin()), std::move(node));
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
VERIFY( pos != c.end() );
VERIFY( pos->first == 1 );
VERIFY( pos->second == 10 );
VERIFY( pos == std::next(c.begin()) );
}
void
test03()
{
struct less : std::less<int> { };
using std::is_same_v;
using compat_type1 = std::multimap<int, int, less>;
static_assert( is_same_v<test_type::node_type, compat_type1::node_type> );
using compat_type2 = std::map<int, int>;
static_assert( is_same_v<test_type::node_type, compat_type2::node_type> );
using compat_type3 = std::map<int, int, less>;
static_assert( is_same_v<test_type::node_type, compat_type3::node_type> );
}
int
main()
{
test01();
test02();
test03();
}

View File

@ -0,0 +1,119 @@
// Copyright (C) 2016 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-options "-std=gnu++17" }
#include <map>
#include <algorithm>
#include <testsuite_hooks.h>
using test_type = std::multimap<int, int>;
void
test01()
{
bool test __attribute__((unused)) = true;
const test_type c0{ {1, 10}, {1, 11}, {2, 20}, {2, 21}, {3, 30}, {3, 31} };
test_type c1 = c0, c2 = c0;
c1.merge(c2);
for (auto& i : c1)
VERIFY( c1.count(i.first) == (2 * c0.count(i.first)) );
VERIFY( c2.empty() );
c1.clear();
c2 = c0;
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
}
void
test02()
{
bool test __attribute__((unused)) = true;
const test_type c0{ {1, 10}, {1, 11}, {2, 20}, {2, 21}, {3, 30}, {3, 31} };
test_type c1 = c0;
std::multimap<int, int, std::less<>> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1.size() == (2 * c0.size()) );
for (auto& i : c1)
VERIFY( c1.count(i.first) == (2 * c0.count(i.first)) );
VERIFY( c2.empty() );
c1.clear();
c2.insert( c0.begin(), c0.end() );
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
}
void
test03()
{
bool test __attribute__((unused)) = true;
const test_type c0{ {1, 10}, {1, 11}, {2, 20}, {2, 21}, {3, 30}, {3, 31} };
test_type c1 = c0;
std::multimap<int, int, std::greater<>> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1.size() == (2 * c0.size()) );
for (auto& i : c1)
VERIFY( c1.count(i.first) == (2 * c0.count(i.first)) );
VERIFY( c2.empty() );
c1.clear();
c2.insert( c0.begin(), c0.end() );
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
}
void
test04()
{
bool test __attribute__((unused)) = true;
const test_type c0{ {1, 10}, {1, 11}, {2, 20}, {2, 21}, {3, 30}, {3, 31} };
test_type c1 = c0;
std::map<int, int, std::greater<>> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1.size() == (1.5 * c0.size()) );
for (auto& i : c1)
VERIFY( c1.count(i.first) == (1.5 * c0.count(i.first)) );
VERIFY( c2.empty() );
c1.clear();
c2.insert( c0.begin(), c0.end() );
c1.merge(std::move(c2));
VERIFY( c1.size() == (0.5 * c0.size()) );
VERIFY( c2.empty() );
}
int
main()
{
test01();
test02();
test03();
test04();
}

View File

@ -0,0 +1,129 @@
// Copyright (C) 2016 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-options "-std=gnu++17" }
#include <set>
#include <algorithm>
#include <testsuite_hooks.h>
using test_type = std::multiset<int>;
void
test01()
{
bool test __attribute__((unused)) = true;
test_type c{ 1, 1, 2, 2, 3, 3 };
test_type::node_type node;
test_type::iterator pos;
node = c.extract(0);
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
pos = c.insert(std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
VERIFY( pos == c.end() );
node = c.extract(1);
VERIFY( (bool)node );
VERIFY( !node.empty() );
VERIFY( c.size() == 5 );
VERIFY( node.get_allocator() == c.get_allocator() );
VERIFY( node.value() == 1 );
node.value() = 4;
VERIFY( node.value() == 4 );
pos = c.insert(std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
VERIFY( pos != c.end() );
VERIFY( *pos == 4 );
VERIFY( c.count(1) == 1 );
VERIFY( c.count(4) == 1 );
VERIFY( std::is_sorted(c.begin(), c.end()) );
pos = c.insert(c.begin(), std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
VERIFY( pos == c.end() );
node = c.extract(1);
pos = c.insert(c.begin(), std::move(node));
VERIFY( !node );
VERIFY( c.size() == 6 );
VERIFY( pos != c.end() );
VERIFY( *pos == 1 );
test_type c2 = c;
node = c2.extract(1);
pos = c.insert(std::move(node));
VERIFY( pos != c.end() );
VERIFY( node.empty() );
VERIFY( *pos == 1 );
}
void
test02()
{
bool test __attribute__((unused)) = true;
test_type c{ 1, 1, 2, 2, 3, 3 };
test_type::node_type node;
test_type::iterator pos;
node = c.extract(c.begin());
VERIFY( !node.empty() );
VERIFY( c.size() == 5 );
VERIFY( node.get_allocator() == c.get_allocator() );
VERIFY( node.value() == 1 );
pos = c.insert(std::next(c.begin()), std::move(node));
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
VERIFY( pos != c.end() );
VERIFY( *pos == 1 );
VERIFY( pos == std::next(c.begin()) );
}
void
test03()
{
struct less : std::less<int> { };
using std::is_same_v;
using compat_type1 = std::multiset<int, less>;
static_assert( is_same_v<test_type::node_type, compat_type1::node_type> );
using compat_type2 = std::set<int>;
static_assert( is_same_v<test_type::node_type, compat_type2::node_type> );
using compat_type3 = std::set<int, less>;
static_assert( is_same_v<test_type::node_type, compat_type3::node_type> );
}
int
main()
{
test01();
test02();
test03();
}

View File

@ -0,0 +1,117 @@
// Copyright (C) 2016 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-options "-std=gnu++17" }
#include <set>
#include <algorithm>
#include <testsuite_hooks.h>
using test_type = std::multiset<int>;
void
test01()
{
bool test __attribute__((unused)) = true;
test_type c0{ 1, 1, 2, 2, 3, 3 };
test_type c1 = c0, c2 = c0;
c1.merge(c2);
for (auto i : c1)
VERIFY( c1.count(i) == (2 * c0.count(i)) );
VERIFY( c2.empty() );
c1.clear();
c2 = c0;
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
}
void
test02()
{
bool test __attribute__((unused)) = true;
test_type c0{ 1, 1, 2, 2, 3, 3 };
test_type c1 = c0;
std::multiset<int, std::less<>> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1.size() == (2 * c0.size()) );
for (auto i : c1)
VERIFY( c1.count(i) == (2 * c0.count(i)) );
VERIFY( c2.empty() );
c1.clear();
c2.insert( c0.begin(), c0.end() );
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
}
void
test03()
{
const test_type c0{ 1, 1, 2, 2, 3, 3 };
test_type c1 = c0;
std::multiset<int, std::greater<>> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1.size() == (2 * c0.size()) );
for (auto i : c1)
VERIFY( c1.count(i) == (2 * c0.count(i)) );
VERIFY( c2.empty() );
c1.clear();
c2.insert( c0.begin(), c0.end() );
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
}
void
test04()
{
bool test __attribute__((unused)) = true;
const test_type c0{ 1, 1, 2, 2, 3, 3 };
test_type c1 = c0;
std::set<int, std::greater<>> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1.size() == (1.5 * c0.size()) );
for (auto& i : c1)
VERIFY( c1.count(i) == (1.5 * c0.count(i)) );
VERIFY( c2.empty() );
c1.clear();
c2.insert( c0.begin(), c0.end() );
c1.merge(std::move(c2));
VERIFY( c1.size() == (0.5 * c0.size()) );
VERIFY( c2.empty() );
}
int
main()
{
test01();
test02();
test03();
test04();
}

View File

@ -0,0 +1,138 @@
// Copyright (C) 2016 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-options "-std=gnu++17" }
#include <set>
#include <algorithm>
#include <testsuite_hooks.h>
using test_type = std::set<int>;
void
test01()
{
bool test __attribute__((unused)) = true;
test_type c{ 1, 2, 3 };
test_type::node_type node;
test_type::insert_return_type ins;
test_type::iterator pos;
node = c.extract(0);
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
ins = c.insert(std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
VERIFY( !ins.inserted );
VERIFY( !ins.node );
VERIFY( ins.position == c.end() );
node = c.extract(1);
VERIFY( (bool)node );
VERIFY( !node.empty() );
VERIFY( c.size() == 2 );
VERIFY( node.get_allocator() == c.get_allocator() );
VERIFY( node.value() == 1 );
node.value() = 4;
VERIFY( node.value() == 4 );
ins = c.insert(std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
VERIFY( ins.inserted );
VERIFY( !ins.node );
VERIFY( ins.position != c.end() );
VERIFY( *ins.position == 4 );
VERIFY( c.count(1) == 0 );
VERIFY( c.count(4) == 1 );
VERIFY( std::is_sorted(c.begin(), c.end()) );
pos = c.insert(c.begin(), std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
VERIFY( pos == c.end() );
node = c.extract(2);
pos = c.insert(c.begin(), std::move(node));
VERIFY( c.size() == 3 );
VERIFY( pos != c.end() );
VERIFY( *pos == 2 );
test_type c2 = c;
node = c2.extract(3);
ins = c.insert(std::move(node));
VERIFY( node.empty() );
VERIFY( ins.position != c.end() );
VERIFY( !ins.inserted );
VERIFY( !ins.node.empty() );
VERIFY( ins.node.value() == 3 );
VERIFY( *ins.position == ins.node.value() );
}
void
test02()
{
bool test __attribute__((unused)) = true;
test_type c{ 1, 2, 3 };
test_type::node_type node;
test_type::insert_return_type ins;
node = c.extract(c.begin());
VERIFY( (bool)node );
VERIFY( !node.empty() );
VERIFY( c.size() == 2 );
VERIFY( node.get_allocator() == c.get_allocator() );
VERIFY( node.value() == 1 );
ins = c.insert(std::move(node));
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
VERIFY( ins.inserted );
VERIFY( !ins.node );
VERIFY( ins.position != c.end() );
VERIFY( *ins.position == 1 );
}
void
test03()
{
struct less : std::less<int> { };
using std::is_same_v;
using compat_type1 = std::set<int, less>;
static_assert( is_same_v<test_type::node_type, compat_type1::node_type> );
using compat_type2 = std::multiset<int>;
static_assert( is_same_v<test_type::node_type, compat_type2::node_type> );
using compat_type3 = std::multiset<int, less>;
static_assert( is_same_v<test_type::node_type, compat_type3::node_type> );
}
int
main()
{
test01();
test02();
test03();
}

View File

@ -0,0 +1,143 @@
// Copyright (C) 2016 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-options "-std=gnu++17" }
#include <set>
#include <algorithm>
#include <testsuite_hooks.h>
using test_type = std::set<int>;
void
test01()
{
bool test __attribute__((unused)) = true;
const test_type c0{ 1, 2, 3 };
test_type c1 = c0, c2 = c0;
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( c2 == c0 );
c1.clear();
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
c2.merge(std::move(c1));
VERIFY( c1.empty() );
VERIFY( c2 == c0 );
}
void
test02()
{
bool test __attribute__((unused)) = true;
const test_type c0{ 1, 2, 3 };
test_type c1 = c0;
std::set<int, std::less<>> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( std::equal(c2.begin(), c2.end(), c0.begin(), c0.end()) );
c1.clear();
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
c2.merge(std::move(c1));
VERIFY( c1.empty() );
VERIFY( std::equal(c2.begin(), c2.end(), c0.begin(), c0.end()) );
}
void
test03()
{
bool test __attribute__((unused)) = true;
const test_type c0{ 1, 2, 3 };
test_type c1 = c0;
std::set<int, std::greater<>> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( std::equal(c2.rbegin(), c2.rend(), c0.begin(), c0.end()) );
c1.clear();
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
c2.merge(c1);
VERIFY( c1.empty() );
VERIFY( std::equal(c2.rbegin(), c2.rend(), c0.begin(), c0.end()) );
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
}
void
test04()
{
bool test __attribute__((unused)) = true;
const test_type c0{ 1, 2, 3 };
test_type c1 = c0;
std::multiset<int, std::greater<>> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( std::equal(c2.rbegin(), c2.rend(), c0.begin(), c0.end()) );
c1.clear();
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
c2.merge(c1);
VERIFY( c1.empty() );
VERIFY( std::equal(c2.rbegin(), c2.rend(), c0.begin(), c0.end()) );
c1 = c0;
c2.merge(c1);
VERIFY( c1.empty() );
VERIFY( c2.size() == (2 * c0.size()) );
VERIFY( std::is_sorted(c2.begin(), c2.end(), c2.value_comp()) );
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( std::equal(c2.rbegin(), c2.rend(), c0.begin(), c0.end()) );
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( std::equal(c2.rbegin(), c2.rend(), c0.begin(), c0.end()) );
c1.clear();
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
}
int
main()
{
test01();
test02();
test03();
test04();
}

View File

@ -0,0 +1,148 @@
// Copyright (C) 2016 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-options "-std=gnu++17" }
#include <unordered_map>
#include <testsuite_hooks.h>
using test_type = std::unordered_map<int, int>;
void
test01()
{
bool test __attribute__((unused)) = true;
test_type c{ {1, 10}, {2, 20}, {3, 30} };
test_type::node_type node;
test_type::insert_return_type ins;
test_type::iterator pos;
node = c.extract(0);
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
ins = c.insert(std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
VERIFY( !ins.inserted );
VERIFY( !ins.node );
VERIFY( ins.position == c.end() );
node = c.extract(1);
VERIFY( (bool)node );
VERIFY( !node.empty() );
VERIFY( c.size() == 2 );
VERIFY( node.get_allocator() == c.get_allocator() );
VERIFY( node.key() == 1 );
VERIFY( node.mapped() == 10 );
node.key() = 4;
node.mapped() = 40;
VERIFY( node.key() == 4 );
VERIFY( node.mapped() == 40 );
ins = c.insert(std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
VERIFY( ins.inserted );
VERIFY( !ins.node );
VERIFY( ins.position != c.end() );
VERIFY( ins.position->first == 4 );
VERIFY( ins.position->second == 40 );
VERIFY( c.count(1) == 0 );
VERIFY( c.count(4) == 1 );
pos = c.insert(c.begin(), std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
VERIFY( pos == c.end() );
pos = c.insert(c.begin(), c.extract(2));
VERIFY( c.size() == 3 );
VERIFY( pos != c.end() );
VERIFY( pos->first == 2 );
VERIFY( pos->second == 20 );
test_type c2 = c;
node = c2.extract(3);
ins = c.insert(std::move(node));
VERIFY( node.empty() );
VERIFY( ins.position != c.end() );
VERIFY( !ins.inserted );
VERIFY( !ins.node.empty() );
VERIFY( ins.node.key() == 3 );
VERIFY( ins.node.mapped() == 30 );
auto hasher = c.hash_function();
VERIFY( hasher(ins.position->first) == hasher(ins.node.key()) );
auto eq = c.key_eq();
VERIFY( eq(ins.position->first, ins.node.key()) );
}
void
test02()
{
bool test __attribute__((unused)) = true;
test_type c{ {1, 10}, {2, 20}, {3, 30} };
test_type::node_type node;
test_type::insert_return_type ins;
const int key = c.begin()->first;
node = c.extract(c.begin());
VERIFY( (bool)node );
VERIFY( !node.empty() );
VERIFY( c.size() == 2 );
VERIFY( node.get_allocator() == c.get_allocator() );
VERIFY( node.key() == key );
VERIFY( node.mapped() == (key * 10) );
ins = c.insert(std::move(node));
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
VERIFY( ins.inserted );
VERIFY( !ins.node );
VERIFY( ins.position != c.end() );
VERIFY( ins.position->first == key );
VERIFY( ins.position->second == (key * 10) );
}
void
test03()
{
struct hash : std::hash<int> { };
struct equal : std::equal_to<int> { };
using std::is_same_v;
using compat_type1 = std::unordered_map<int, int, hash, equal>;
static_assert( is_same_v<test_type::node_type, compat_type1::node_type> );
using compat_type2 = std::unordered_multimap<int, int>;
static_assert( is_same_v<test_type::node_type, compat_type2::node_type> );
using compat_type3 = std::unordered_multimap<int, int, hash, equal>;
static_assert( is_same_v<test_type::node_type, compat_type3::node_type> );
}
int
main()
{
test01();
test02();
test03();
}

View File

@ -0,0 +1,140 @@
// Copyright (C) 2016 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-options "-std=gnu++17" }
#include <unordered_map>
#include <algorithm>
#include <testsuite_hooks.h>
using test_type = std::unordered_map<int, int>;
struct hash {
auto operator()(int i) const noexcept { return ~std::hash<int>()(i); }
};
struct equal : std::equal_to<> { };
template<typename C1, typename C2>
bool equal_elements(const C1& c1, const C2& c2)
{
if (c2.size() != c1.size())
return false;
for (auto& i : c1)
if (c2.count(i.first) != c1.count(i.first))
return false;
return true;
}
void
test01()
{
bool test __attribute__((unused)) = true;
const test_type c0{ {1, 10}, {2, 20}, {3, 30} };
test_type c1 = c0, c2 = c0;
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( c2 == c0 );
c1.clear();
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
c2.merge(std::move(c1));
VERIFY( c1.empty() );
VERIFY( c2 == c0 );
}
void
test02()
{
bool test __attribute__((unused)) = true;
const test_type c0{ {1, 10}, {2, 20}, {3, 30} };
test_type c1 = c0;
std::unordered_map<int, int, hash, equal> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( equal_elements(c2, c0) );
c1.clear();
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
c2.merge(c1);
VERIFY( c1.empty() );
VERIFY( equal_elements(c2, c0) );
c1.merge(std::move(c2));
VERIFY( c2.empty() );
VERIFY( c1 == c0 );
}
void
test03()
{
bool test __attribute__((unused)) = true;
const test_type c0{ {1, 10}, {2, 20}, {3, 30} };
test_type c1 = c0;
std::unordered_multimap<int, int, hash, equal> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( equal_elements(c2, c0) );
c1.clear();
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
c2.merge(c1);
VERIFY( c1.empty() );
VERIFY( equal_elements(c2, c0) );
c1 = c0;
c2.merge(c1);
VERIFY( c1.empty() );
VERIFY( c2.size() == (2 * c0.size()) );
VERIFY( c2.count(1) == 2 );
VERIFY( c2.count(2) == 2 );
VERIFY( c2.count(3) == 2 );
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( equal_elements(c2, c0) );
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( equal_elements(c2, c0) );
c1.clear();
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
}
int
main()
{
test01();
test02();
test03();
}

View File

@ -0,0 +1,138 @@
// Copyright (C) 2016 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-options "-std=gnu++17" }
#include <unordered_map>
#include <testsuite_hooks.h>
using test_type = std::unordered_multimap<int, int>;
void
test01()
{
bool test __attribute__((unused)) = true;
test_type c{ {1, 10}, { 1, 11 }, {2, 20}, { 2, 21}, {3, 30}, { 3, 31 } };
test_type::node_type node;
test_type::iterator pos;
node = c.extract(0);
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
pos = c.insert(std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
VERIFY( pos == c.end() );
node = c.extract(1);
VERIFY( (bool)node );
VERIFY( !node.empty() );
VERIFY( c.size() == 5 );
VERIFY( node.get_allocator() == c.get_allocator() );
VERIFY( node.key() == 1 );
int mapped = node.mapped();
VERIFY( mapped == 10 || mapped == 11 );
node.key() = 4;
node.mapped() = 40;
VERIFY( node.key() == 4 );
VERIFY( node.mapped() == 40 );
pos = c.insert(std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
VERIFY( pos != c.end() );
VERIFY( pos->first == 4 );
VERIFY( pos->second == 40 );
pos = c.insert(c.begin(), std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
VERIFY( pos == c.end() );
node = c.extract(1);
mapped = node.mapped();
pos = c.insert(c.begin(), std::move(node));
VERIFY( !node );
VERIFY( c.size() == 6 );
VERIFY( pos != c.end() );
VERIFY( pos->first == 1 );
VERIFY( pos->second == mapped );
test_type c2 = c;
node = c2.extract(1);
mapped = node.mapped();
pos = c.insert(std::move(node));
VERIFY( pos != c.end() );
VERIFY( node.empty() );
VERIFY( pos->first == 1 );
VERIFY( pos->second == mapped );
}
void
test02()
{
bool test __attribute__((unused)) = true;
test_type c{ {1, 10}, { 1, 11 }, {2, 20}, { 2, 21}, {3, 30}, { 3, 31 } };
test_type::node_type node;
test_type::iterator pos;
const int key = c.begin()->first;
const int mapped = c.begin()->second;
node = c.extract(c.begin());
VERIFY( !node.empty() );
VERIFY( c.size() == 5 );
VERIFY( node.get_allocator() == c.get_allocator() );
VERIFY( node.key() == key );
VERIFY( node.mapped() == mapped );
pos = c.insert(std::move(node));
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
VERIFY( pos != c.end() );
VERIFY( pos->first == key );
VERIFY( pos->second == mapped );
}
void
test03()
{
struct hash : std::hash<int> { };
struct equal : std::equal_to<int> { };
using std::is_same_v;
using compat_type1 = std::unordered_multimap<int, int, hash, equal>;
static_assert( is_same_v<test_type::node_type, compat_type1::node_type> );
using compat_type2 = std::unordered_map<int, int>;
static_assert( is_same_v<test_type::node_type, compat_type2::node_type> );
using compat_type3 = std::unordered_map<int, int, hash, equal>;
static_assert( is_same_v<test_type::node_type, compat_type3::node_type> );
}
int
main()
{
test01();
test02();
test03();
}

View File

@ -0,0 +1,123 @@
// Copyright (C) 2016 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-options "-std=gnu++17" }
#include <unordered_map>
#include <algorithm>
#include <testsuite_hooks.h>
using test_type = std::unordered_multimap<int, int>;
struct hash {
auto operator()(int i) const noexcept { return ~std::hash<int>()(i); }
};
struct equal : std::equal_to<> { };
void
test01()
{
bool test __attribute__((unused)) = true;
const test_type c0{ {1, 10}, {1, 11}, {2, 20}, {2, 21}, {3, 30}, {3, 31} };
test_type c1 = c0, c2 = c0;
c1.merge(c2);
for (auto& i : c1)
VERIFY( c1.count(i.first) == (2 * c0.count(i.first)) );
VERIFY( c2.empty() );
c1.clear();
c2 = c0;
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
}
void
test02()
{
bool test __attribute__((unused)) = true;
const test_type c0{ {1, 10}, {1, 11}, {2, 20}, {2, 21}, {3, 30}, {3, 31} };
test_type c1 = c0;
std::unordered_multimap<int, int, hash, equal> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1.size() == (2 * c0.size()) );
for (auto& i : c1)
VERIFY( c1.count(i.first) == (2 * c0.count(i.first)) );
VERIFY( c2.empty() );
c1.clear();
c2.insert( c0.begin(), c0.end() );
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
}
void
test03()
{
bool test __attribute__((unused)) = true;
const test_type c0{ {1, 10}, {1, 11}, {2, 20}, {2, 21}, {3, 30}, {3, 31} };
test_type c1 = c0;
std::unordered_multimap<int, int, hash, equal> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1.size() == (2 * c0.size()) );
for (auto& i : c1)
VERIFY( c1.count(i.first) == (2 * c0.count(i.first)) );
VERIFY( c2.empty() );
c1.clear();
c2.insert( c0.begin(), c0.end() );
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
}
void
test04()
{
bool test __attribute__((unused)) = true;
const test_type c0{ {1, 10}, {1, 11}, {2, 20}, {2, 21}, {3, 30}, {3, 31} };
test_type c1 = c0;
std::unordered_map<int, int, hash, equal> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1.size() == (1.5 * c0.size()) );
for (auto& i : c1)
VERIFY( c1.count(i.first) == (1.5 * c0.count(i.first)) );
VERIFY( c2.empty() );
c1.clear();
c2.insert( c0.begin(), c0.end() );
c1.merge(std::move(c2));
VERIFY( c1.size() == (0.5 * c0.size()) );
VERIFY( c2.empty() );
}
int
main()
{
test01();
test02();
test03();
test04();
}

View File

@ -0,0 +1,128 @@
// Copyright (C) 2016 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-options "-std=gnu++17" }
#include <unordered_set>
#include <testsuite_hooks.h>
using test_type = std::unordered_multiset<int>;
void
test01()
{
bool test __attribute__((unused)) = true;
test_type c{ 1, 1, 2, 2, 3, 3 };
test_type::node_type node;
test_type::iterator pos;
node = c.extract(0);
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
pos = c.insert(std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
VERIFY( pos == c.end() );
node = c.extract(1);
VERIFY( (bool)node );
VERIFY( !node.empty() );
VERIFY( c.size() == 5 );
VERIFY( node.get_allocator() == c.get_allocator() );
VERIFY( node.value() == 1 );
node.value() = 4;
VERIFY( node.value() == 4 );
pos = c.insert(std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
VERIFY( pos != c.end() );
VERIFY( *pos == 4 );
VERIFY( c.count(1) == 1 );
VERIFY( c.count(4) == 1 );
pos = c.insert(c.begin(), std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
VERIFY( pos == c.end() );
node = c.extract(1);
pos = c.insert(c.begin(), std::move(node));
VERIFY( !node );
VERIFY( c.size() == 6 );
VERIFY( pos != c.end() );
VERIFY( *pos == 1 );
test_type c2 = c;
node = c2.extract(1);
pos = c.insert(std::move(node));
VERIFY( pos != c.end() );
VERIFY( node.empty() );
VERIFY( *pos == 1 );
}
void
test02()
{
bool test __attribute__((unused)) = true;
test_type c{ 1, 1, 2, 2, 3, 3 };
test_type::node_type node;
test_type::iterator pos;
const int val = *c.begin();
node = c.extract(c.begin());
VERIFY( !node.empty() );
VERIFY( c.size() == 5 );
VERIFY( node.get_allocator() == c.get_allocator() );
VERIFY( node.value() == val );
pos = c.insert(std::move(node));
VERIFY( node.empty() );
VERIFY( c.size() == 6 );
VERIFY( pos != c.end() );
VERIFY( *pos == val );
}
void
test03()
{
struct hash : std::hash<int> { };
struct equal : std::equal_to<int> { };
using std::is_same_v;
using compat_type1 = std::unordered_multiset<int, hash, equal>;
static_assert( is_same_v<test_type::node_type, compat_type1::node_type> );
using compat_type2 = std::unordered_set<int>;
static_assert( is_same_v<test_type::node_type, compat_type2::node_type> );
using compat_type3 = std::unordered_set<int, hash, equal>;
static_assert( is_same_v<test_type::node_type, compat_type3::node_type> );
}
int
main()
{
test01();
test02();
test03();
}

View File

@ -0,0 +1,121 @@
// Copyright (C) 2016 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-options "-std=gnu++17" }
#include <unordered_set>
#include <algorithm>
#include <testsuite_hooks.h>
using test_type = std::unordered_multiset<int>;
struct hash {
auto operator()(int i) const noexcept { return ~std::hash<int>()(i); }
};
struct equal : std::equal_to<> { };
void
test01()
{
bool test __attribute__((unused)) = true;
test_type c0{ 1, 1, 2, 2, 3, 3 };
test_type c1 = c0, c2 = c0;
c1.merge(c2);
for (auto i : c1)
VERIFY( c1.count(i) == (2 * c0.count(i)) );
VERIFY( c2.empty() );
c1.clear();
c2 = c0;
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
}
void
test02()
{
bool test __attribute__((unused)) = true;
test_type c0{ 1, 1, 2, 2, 3, 3 };
test_type c1 = c0;
std::unordered_multiset<int, hash, equal> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1.size() == (2 * c0.size()) );
for (auto i : c1)
VERIFY( c1.count(i) == (2 * c0.count(i)) );
VERIFY( c2.empty() );
c1.clear();
c2.insert( c0.begin(), c0.end() );
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
}
void
test03()
{
const test_type c0{ 1, 1, 2, 2, 3, 3 };
test_type c1 = c0;
std::unordered_multiset<int, hash, equal> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1.size() == (2 * c0.size()) );
for (auto i : c1)
VERIFY( c1.count(i) == (2 * c0.count(i)) );
VERIFY( c2.empty() );
c1.clear();
c2.insert( c0.begin(), c0.end() );
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
}
void
test04()
{
bool test __attribute__((unused)) = true;
const test_type c0{ 1, 1, 2, 2, 3, 3 };
test_type c1 = c0;
std::unordered_set<int, hash, equal> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1.size() == (1.5 * c0.size()) );
for (auto& i : c1)
VERIFY( c1.count(i) == (1.5 * c0.count(i)) );
VERIFY( c2.empty() );
c1.clear();
c2.insert( c0.begin(), c0.end() );
c1.merge(std::move(c2));
VERIFY( c1.size() == (0.5 * c0.size()) );
VERIFY( c2.empty() );
}
int
main()
{
test01();
test02();
test03();
test04();
}

View File

@ -18,7 +18,7 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-error "with noexcept" "" { target *-*-* } 265 }
// { dg-error "with noexcept" "" { target *-*-* } 268 }
#include <unordered_set>

View File

@ -0,0 +1,140 @@
// Copyright (C) 2016 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-options "-std=gnu++17" }
#include <unordered_set>
#include <testsuite_hooks.h>
using test_type = std::unordered_set<int>;
void
test01()
{
bool test __attribute__((unused)) = true;
test_type c{ 1, 2, 3 };
test_type::node_type node;
test_type::insert_return_type ins;
test_type::iterator pos;
node = c.extract(0);
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
ins = c.insert(std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
VERIFY( !ins.inserted );
VERIFY( !ins.node );
VERIFY( ins.position == c.end() );
node = c.extract(1);
VERIFY( (bool)node );
VERIFY( !node.empty() );
VERIFY( c.size() == 2 );
VERIFY( node.get_allocator() == c.get_allocator() );
VERIFY( node.value() == 1 );
node.value() = 4;
VERIFY( node.value() == 4 );
ins = c.insert(std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
VERIFY( ins.inserted );
VERIFY( !ins.node );
VERIFY( ins.position != c.end() );
VERIFY( *ins.position == 4 );
VERIFY( c.count(1) == 0 );
VERIFY( c.count(4) == 1 );
pos = c.insert(c.begin(), std::move(node));
VERIFY( !node );
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
VERIFY( pos == c.end() );
pos = c.insert(c.begin(), c.extract(2));
VERIFY( c.size() == 3 );
VERIFY( pos != c.end() );
VERIFY( *pos == 2 );
test_type c2 = c;
node = c2.extract(3);
ins = c.insert(std::move(node));
VERIFY( node.empty() );
VERIFY( ins.position != c.end() );
VERIFY( !ins.inserted );
VERIFY( !ins.node.empty() );
VERIFY( ins.node.value() == 3 );
auto hasher = c.hash_function();
VERIFY( hasher(*ins.position) == hasher(ins.node.value()) );
auto eq = c.key_eq();
VERIFY( eq(*ins.position, ins.node.value()) );
}
void
test02()
{
bool test __attribute__((unused)) = true;
test_type c{ 1, 2, 3 };
test_type::node_type node;
test_type::insert_return_type ins;
const int val = *c.begin();
node = c.extract(c.begin());
VERIFY( (bool)node );
VERIFY( !node.empty() );
VERIFY( c.size() == 2 );
VERIFY( node.get_allocator() == c.get_allocator() );
VERIFY( node.value() == val );
ins = c.insert(std::move(node));
VERIFY( node.empty() );
VERIFY( c.size() == 3 );
VERIFY( ins.inserted );
VERIFY( !ins.node );
VERIFY( ins.position != c.end() );
VERIFY( *ins.position == val );
}
void
test03()
{
struct hash : std::hash<int> { };
struct equal : std::equal_to<int> { };
using std::is_same_v;
using compat_type1 = std::unordered_set<int, hash, equal>;
static_assert( is_same_v<test_type::node_type, compat_type1::node_type> );
using compat_type2 = std::unordered_multiset<int>;
static_assert( is_same_v<test_type::node_type, compat_type2::node_type> );
using compat_type3 = std::unordered_multiset<int, hash, equal>;
static_assert( is_same_v<test_type::node_type, compat_type3::node_type> );
}
int
main()
{
test01();
test02();
test03();
}

View File

@ -0,0 +1,140 @@
// Copyright (C) 2016 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-options "-std=gnu++17" }
#include <unordered_set>
#include <algorithm>
#include <testsuite_hooks.h>
using test_type = std::unordered_set<int>;
struct hash {
auto operator()(int i) const noexcept { return ~std::hash<int>()(i); }
};
struct equal : std::equal_to<> { };
template<typename C1, typename C2>
bool equal_elements(const C1& c1, const C2& c2)
{
if (c2.size() != c1.size())
return false;
for (auto& i : c1)
if (c2.count(i) != c1.count(i))
return false;
return true;
}
void
test01()
{
bool test __attribute__((unused)) = true;
const test_type c0{ 1, 2, 3, };
test_type c1 = c0, c2 = c0;
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( c2 == c0 );
c1.clear();
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
c2.merge(std::move(c1));
VERIFY( c1.empty() );
VERIFY( c2 == c0 );
}
void
test02()
{
bool test __attribute__((unused)) = true;
const test_type c0{ 1, 2, 3, };
test_type c1 = c0;
std::unordered_set<int, hash, equal> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( equal_elements(c2, c0) );
c1.clear();
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
c2.merge(c1);
VERIFY( c1.empty() );
VERIFY( equal_elements(c2, c0) );
c1.merge(std::move(c2));
VERIFY( c2.empty() );
VERIFY( c1 == c0 );
}
void
test03()
{
bool test __attribute__((unused)) = true;
const test_type c0{ 1, 2, 3, };
test_type c1 = c0;
std::unordered_multiset<int, hash, equal> c2( c0.begin(), c0.end() );
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( equal_elements(c2, c0) );
c1.clear();
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
c2.merge(c1);
VERIFY( c1.empty() );
VERIFY( equal_elements(c2, c0) );
c1 = c0;
c2.merge(c1);
VERIFY( c1.empty() );
VERIFY( c2.size() == (2 * c0.size()) );
VERIFY( c2.count(1) == 2 );
VERIFY( c2.count(2) == 2 );
VERIFY( c2.count(3) == 2 );
c1.merge(c2);
VERIFY( c1 == c0 );
VERIFY( equal_elements(c2, c0) );
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( equal_elements(c2, c0) );
c1.clear();
c1.merge(std::move(c2));
VERIFY( c1 == c0 );
VERIFY( c2.empty() );
}
int
main()
{
test01();
test02();
test03();
}

View File

@ -27,12 +27,15 @@
#include <string_view>
#include <string>
#include <map>
#include <unordered_set>
#include <iostream>
using std::any;
using std::optional;
using std::variant;
using std::string_view;
using std::map;
using std::unordered_set;
int
main()
@ -83,10 +86,21 @@ main()
// { dg-final { note-test v3 {std::variant<float, int, std::string_view> [index 1] = {3}} } }
variant<float, int, string_view> v4{ str };
// { dg-final { note-test v4 {std::variant<float, int, std::string_view> [index 2] = {"string"}} } }
variant<string_view&> vref{str};
// { dg-final { note-test vref {std::variant<std::basic_string_view<char, std::char_traits<char> > &> [index 0] = {"string"}} } }
map<int, string_view> m{ {1, "one"} };
map<int, string_view>::node_type n0;
// { dg-final { note-test n0 {empty node handle for map}}}
map<int, string_view>::node_type n1 = m.extract(1);
// { dg-final { note-test n1 {node handle for map with element = {{first = 1, second = "two"}}}}}
unordered_set<int> s{ 3, 4 };
unordered_set<int>::node_type n2;
// { dg-final { note-test n2 {empty node handle for unordered set}}}
unordered_set<int>::node_type n3 = s.extract(3);
// { dg-final { note-test n1 {node handle for unordered set with element = {3}}}}
std::cout << "\n";
return 0; // Mark SPOT
}