mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-11 20:31:05 +08:00
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:
parent
475edec070
commit
2dbe56bdfb
@ -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.
|
||||
|
@ -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>
|
@ -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 >= 201411</code>,
|
||||
<code class="code"> __cpp_lib_unordered_map_try_emplace >= 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 >= 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 >= 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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
||||
|
330
libstdc++-v3/include/bits/node_handle.h
Normal file
330
libstdc++-v3/include/bits/node_handle.h
Normal 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
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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); }
|
||||
|
@ -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); }
|
||||
|
@ -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)
|
||||
|
147
libstdc++-v3/testsuite/23_containers/map/modifiers/extract.cc
Normal file
147
libstdc++-v3/testsuite/23_containers/map/modifiers/extract.cc
Normal 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();
|
||||
}
|
147
libstdc++-v3/testsuite/23_containers/map/modifiers/merge.cc
Normal file
147
libstdc++-v3/testsuite/23_containers/map/modifiers/merge.cc
Normal 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();
|
||||
}
|
@ -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();
|
||||
}
|
119
libstdc++-v3/testsuite/23_containers/multimap/modifiers/merge.cc
Normal file
119
libstdc++-v3/testsuite/23_containers/multimap/modifiers/merge.cc
Normal 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();
|
||||
}
|
@ -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();
|
||||
}
|
117
libstdc++-v3/testsuite/23_containers/multiset/modifiers/merge.cc
Normal file
117
libstdc++-v3/testsuite/23_containers/multiset/modifiers/merge.cc
Normal 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();
|
||||
}
|
138
libstdc++-v3/testsuite/23_containers/set/modifiers/extract.cc
Normal file
138
libstdc++-v3/testsuite/23_containers/set/modifiers/extract.cc
Normal 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();
|
||||
}
|
143
libstdc++-v3/testsuite/23_containers/set/modifiers/merge.cc
Normal file
143
libstdc++-v3/testsuite/23_containers/set/modifiers/merge.cc
Normal 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();
|
||||
}
|
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
@ -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>
|
||||
|
||||
|
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user