mirror of
https://github.com/boostorg/unordered.git
synced 2025-05-09 23:23:59 +00:00
added pull to open-addressing containers (#309)
* added pull to open-addressing containers * added pull_tests.cpp * guarded pull against exceptions in mid init_type construction
This commit is contained in:
parent
2907fe8c98
commit
3dde65b2ef
@ -6,6 +6,11 @@
|
|||||||
:github-pr-url: https://github.com/boostorg/unordered/pull
|
:github-pr-url: https://github.com/boostorg/unordered/pull
|
||||||
:cpp: C++
|
:cpp: C++
|
||||||
|
|
||||||
|
== Release 1.89.0
|
||||||
|
|
||||||
|
* Added `pull(const_iterator)` to open-addressing containers. This operation
|
||||||
|
allows for efficient removal and retrieval of an element via move construction.
|
||||||
|
|
||||||
== Release 1.88.0
|
== Release 1.88.0
|
||||||
|
|
||||||
* Migrated the documentation to a multipage format using Antora.
|
* Migrated the documentation to a multipage format using Antora.
|
||||||
|
@ -168,6 +168,7 @@ namespace unordered {
|
|||||||
void xref:#unordered_flat_map_swap[swap](unordered_flat_map& other)
|
void xref:#unordered_flat_map_swap[swap](unordered_flat_map& other)
|
||||||
noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
|
noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
|
||||||
boost::allocator_traits<Allocator>::propagate_on_container_swap::value);
|
boost::allocator_traits<Allocator>::propagate_on_container_swap::value);
|
||||||
|
init_type xref:#unordered_flat_map_pull[pull](const_iterator position);
|
||||||
void xref:#unordered_flat_map_clear[clear]() noexcept;
|
void xref:#unordered_flat_map_clear[clear]() noexcept;
|
||||||
|
|
||||||
template<class H2, class P2>
|
template<class H2, class P2>
|
||||||
@ -1126,6 +1127,16 @@ Throws:;; Nothing unless `key_equal` or `hasher` throw on swapping.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
==== pull
|
||||||
|
```c++
|
||||||
|
init_type pull(const_iterator position);
|
||||||
|
```
|
||||||
|
|
||||||
|
Move-constructs an `init_value` `x` from the element pointed to by `position`,
|
||||||
|
erases the element and returns `x`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
==== clear
|
==== clear
|
||||||
```c++
|
```c++
|
||||||
void clear() noexcept;
|
void clear() noexcept;
|
||||||
|
@ -135,6 +135,7 @@ namespace unordered {
|
|||||||
void xref:#unordered_flat_set_swap[swap](unordered_flat_set& other)
|
void xref:#unordered_flat_set_swap[swap](unordered_flat_set& other)
|
||||||
noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
|
noexcept(boost::allocator_traits<Allocator>::is_always_equal::value ||
|
||||||
boost::allocator_traits<Allocator>::propagate_on_container_swap::value);
|
boost::allocator_traits<Allocator>::propagate_on_container_swap::value);
|
||||||
|
init_type xref:#unordered_flat_set_pull[pull](const_iterator position);
|
||||||
void xref:#unordered_flat_set_clear[clear]() noexcept;
|
void xref:#unordered_flat_set_clear[clear]() noexcept;
|
||||||
|
|
||||||
template<class H2, class P2>
|
template<class H2, class P2>
|
||||||
@ -932,6 +933,16 @@ Throws:;; Nothing unless `key_equal` or `hasher` throw on swapping.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
==== pull
|
||||||
|
```c++
|
||||||
|
init_type pull(const_iterator position);
|
||||||
|
```
|
||||||
|
|
||||||
|
Move-constructs an `init_value` `x` from the element pointed to by `position`,
|
||||||
|
erases the element and returns `x`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
==== clear
|
==== clear
|
||||||
```c++
|
```c++
|
||||||
void clear() noexcept;
|
void clear() noexcept;
|
||||||
|
@ -172,6 +172,7 @@ namespace unordered {
|
|||||||
node_type xref:#unordered_node_map_extract_by_position[extract](const_iterator position);
|
node_type xref:#unordered_node_map_extract_by_position[extract](const_iterator position);
|
||||||
node_type xref:#unordered_node_map_extract_by_key[extract](const key_type& key);
|
node_type xref:#unordered_node_map_extract_by_key[extract](const key_type& key);
|
||||||
template<class K> node_type xref:#unordered_node_map_extract_by_key[extract](K&& key);
|
template<class K> node_type xref:#unordered_node_map_extract_by_key[extract](K&& key);
|
||||||
|
init_type xref:#unordered_node_map_pull[pull](const_iterator position);
|
||||||
void xref:#unordered_node_map_clear[clear]() noexcept;
|
void xref:#unordered_node_map_clear[clear]() noexcept;
|
||||||
|
|
||||||
template<class H2, class P2>
|
template<class H2, class P2>
|
||||||
@ -1224,6 +1225,16 @@ Notes:;; The `template<class K>` overload only participates in overload resoluti
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
==== pull
|
||||||
|
```c++
|
||||||
|
init_type pull(const_iterator position);
|
||||||
|
```
|
||||||
|
|
||||||
|
Move-constructs an `init_value` `x` from the element pointed to by `position`,
|
||||||
|
erases the element and returns `x`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
==== clear
|
==== clear
|
||||||
```c++
|
```c++
|
||||||
void clear() noexcept;
|
void clear() noexcept;
|
||||||
|
@ -140,6 +140,7 @@ namespace unordered {
|
|||||||
node_type xref:#unordered_node_set_extract_by_position[extract](const_iterator position);
|
node_type xref:#unordered_node_set_extract_by_position[extract](const_iterator position);
|
||||||
node_type xref:#unordered_node_set_extract_by_key[extract](const key_type& key);
|
node_type xref:#unordered_node_set_extract_by_key[extract](const key_type& key);
|
||||||
template<class K> node_type xref:#unordered_node_set_extract_by_key[extract](K&& key);
|
template<class K> node_type xref:#unordered_node_set_extract_by_key[extract](K&& key);
|
||||||
|
init_type xref:#unordered_node_set_pull[pull](const_iterator position);
|
||||||
void xref:#unordered_node_set_clear[clear]() noexcept;
|
void xref:#unordered_node_set_clear[clear]() noexcept;
|
||||||
|
|
||||||
template<class H2, class P2>
|
template<class H2, class P2>
|
||||||
@ -1034,6 +1035,16 @@ Notes:;; The `template<class K>` overload only participates in overload resoluti
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
==== pull
|
||||||
|
```c++
|
||||||
|
init_type pull(const_iterator position);
|
||||||
|
```
|
||||||
|
|
||||||
|
Move-constructs an `init_value` `x` from the element pointed to by `position`,
|
||||||
|
erases the element and returns `x`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
==== clear
|
==== clear
|
||||||
```c++
|
```c++
|
||||||
void clear() noexcept;
|
void clear() noexcept;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* Fast open-addressing hash table.
|
/* Fast open-addressing hash table.
|
||||||
*
|
*
|
||||||
* Copyright 2022-2024 Joaquin M Lopez Munoz.
|
* Copyright 2022-2025 Joaquin M Lopez Munoz.
|
||||||
* Copyright 2023 Christian Mazakas.
|
* Copyright 2023 Christian Mazakas.
|
||||||
* Copyright 2024 Braden Ganetsky.
|
* Copyright 2024 Braden Ganetsky.
|
||||||
* Distributed under the Boost Software License, Version 1.0.
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
@ -495,6 +495,14 @@ public:
|
|||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FORCEINLINE init_type pull(const_iterator pos)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(pos!=end());
|
||||||
|
erase_on_exit e{*this,pos};
|
||||||
|
(void)e;
|
||||||
|
return type_policy::move(type_policy::value_from(*pos.p()));
|
||||||
|
}
|
||||||
|
|
||||||
void swap(table& x)
|
void swap(table& x)
|
||||||
noexcept(noexcept(std::declval<super&>().swap(std::declval<super&>())))
|
noexcept(noexcept(std::declval<super&>().swap(std::declval<super&>())))
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Copyright (C) 2022-2023 Christian Mazakas
|
// Copyright (C) 2022-2023 Christian Mazakas
|
||||||
// Copyright (C) 2024 Joaquin M Lopez Munoz
|
// Copyright (C) 2024-2025 Joaquin M Lopez Munoz
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
@ -438,6 +438,11 @@ namespace boost {
|
|||||||
return table_.erase(key);
|
return table_.erase(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FORCEINLINE init_type pull(const_iterator pos)
|
||||||
|
{
|
||||||
|
return table_.pull(pos);
|
||||||
|
}
|
||||||
|
|
||||||
void swap(unordered_flat_map& rhs) noexcept(
|
void swap(unordered_flat_map& rhs) noexcept(
|
||||||
noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
|
noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Copyright (C) 2022-2023 Christian Mazakas
|
// Copyright (C) 2022-2023 Christian Mazakas
|
||||||
// Copyright (C) 2024 Joaquin M Lopez Munoz
|
// Copyright (C) 2024-2025 Joaquin M Lopez Munoz
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
@ -332,6 +332,11 @@ namespace boost {
|
|||||||
return table_.erase(key);
|
return table_.erase(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FORCEINLINE init_type pull(const_iterator pos)
|
||||||
|
{
|
||||||
|
return table_.pull(pos);
|
||||||
|
}
|
||||||
|
|
||||||
void swap(unordered_flat_set& rhs) noexcept(
|
void swap(unordered_flat_set& rhs) noexcept(
|
||||||
noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
|
noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Copyright (C) 2022-2023 Christian Mazakas
|
// Copyright (C) 2022-2023 Christian Mazakas
|
||||||
// Copyright (C) 2024 Joaquin M Lopez Munoz
|
// Copyright (C) 2024-2025 Joaquin M Lopez Munoz
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
@ -483,6 +483,11 @@ namespace boost {
|
|||||||
return table_.erase(key);
|
return table_.erase(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FORCEINLINE init_type pull(const_iterator pos)
|
||||||
|
{
|
||||||
|
return table_.pull(pos);
|
||||||
|
}
|
||||||
|
|
||||||
void swap(unordered_node_map& rhs) noexcept(
|
void swap(unordered_node_map& rhs) noexcept(
|
||||||
noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
|
noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Copyright (C) 2022-2023 Christian Mazakas
|
// Copyright (C) 2022-2023 Christian Mazakas
|
||||||
// Copyright (C) 2024 Joaquin M Lopez Munoz
|
// Copyright (C) 2024-2025 Joaquin M Lopez Munoz
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
@ -379,6 +379,11 @@ namespace boost {
|
|||||||
return table_.erase(key);
|
return table_.erase(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_FORCEINLINE init_type pull(const_iterator pos)
|
||||||
|
{
|
||||||
|
return table_.pull(pos);
|
||||||
|
}
|
||||||
|
|
||||||
void swap(unordered_node_set& rhs) noexcept(
|
void swap(unordered_node_set& rhs) noexcept(
|
||||||
noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
|
noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
|
||||||
{
|
{
|
||||||
|
@ -123,6 +123,7 @@ foa_tests(SOURCES unordered/uses_allocator.cpp)
|
|||||||
foa_tests(SOURCES unordered/link_test_1.cpp unordered/link_test_2.cpp )
|
foa_tests(SOURCES unordered/link_test_1.cpp unordered/link_test_2.cpp )
|
||||||
foa_tests(SOURCES unordered/scoped_allocator.cpp)
|
foa_tests(SOURCES unordered/scoped_allocator.cpp)
|
||||||
foa_tests(SOURCES unordered/hash_is_avalanching_test.cpp)
|
foa_tests(SOURCES unordered/hash_is_avalanching_test.cpp)
|
||||||
|
foa_tests(SOURCES unordered/pull_tests.cpp)
|
||||||
foa_tests(SOURCES exception/constructor_exception_tests.cpp)
|
foa_tests(SOURCES exception/constructor_exception_tests.cpp)
|
||||||
foa_tests(SOURCES exception/copy_exception_tests.cpp)
|
foa_tests(SOURCES exception/copy_exception_tests.cpp)
|
||||||
foa_tests(SOURCES exception/assign_exception_tests.cpp)
|
foa_tests(SOURCES exception/assign_exception_tests.cpp)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
# Copyright 2006-2008 Daniel James.
|
# Copyright 2006-2008 Daniel James.
|
||||||
# Copyright 2022-2023 Christian Mazakas
|
# Copyright 2022-2023 Christian Mazakas
|
||||||
# Copyright 2024 Joaquin M Lopez Munoz
|
# Copyright 2024-2025 Joaquin M Lopez Munoz
|
||||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
@ -241,6 +241,7 @@ local FOA_TESTS =
|
|||||||
hash_is_avalanching_test
|
hash_is_avalanching_test
|
||||||
fancy_pointer_noleak
|
fancy_pointer_noleak
|
||||||
pmr_allocator_tests
|
pmr_allocator_tests
|
||||||
|
pull_tests
|
||||||
stats_tests
|
stats_tests
|
||||||
node_handle_allocator_tests
|
node_handle_allocator_tests
|
||||||
;
|
;
|
||||||
|
88
test/unordered/pull_tests.cpp
Normal file
88
test/unordered/pull_tests.cpp
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
// Copyright 2025 Joaquin M Lopez Munoz.
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
|
||||||
|
#include "../helpers/test.hpp"
|
||||||
|
#include "../helpers/unordered.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct move_only_type
|
||||||
|
{
|
||||||
|
move_only_type(int n_): n{n_} {}
|
||||||
|
move_only_type(move_only_type&&) = default;
|
||||||
|
move_only_type(const move_only_type&) = delete;
|
||||||
|
|
||||||
|
move_only_type& operator=(move_only_type&&) = default;
|
||||||
|
|
||||||
|
int n;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator==(const move_only_type& x, const move_only_type& y)
|
||||||
|
{
|
||||||
|
return x.n == y.n;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const move_only_type& x, const move_only_type& y)
|
||||||
|
{
|
||||||
|
return x.n < y.n;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t hash_value(const move_only_type& x)
|
||||||
|
{
|
||||||
|
return boost::hash<int>()(x.n);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct from_int
|
||||||
|
{
|
||||||
|
T operator()(int n) const { return T(n); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
struct from_int<std::pair<T, U> >
|
||||||
|
{
|
||||||
|
std::pair<T, U> operator()(int n) const { return {n, -n}; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Container> void test_pull()
|
||||||
|
{
|
||||||
|
Container c;
|
||||||
|
using init_type = typename Container::init_type;
|
||||||
|
|
||||||
|
std::vector<init_type> l1;
|
||||||
|
from_int<init_type> fi;
|
||||||
|
for(int i = 0; i < 1000; ++i ){
|
||||||
|
l1.push_back(fi(i));
|
||||||
|
c.insert(fi(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<init_type> l2;
|
||||||
|
for(auto first = c.cbegin(), last = c.cend(); first != last; )
|
||||||
|
{
|
||||||
|
l2.push_back(c.pull(first++));
|
||||||
|
}
|
||||||
|
BOOST_TEST(c.empty());
|
||||||
|
|
||||||
|
std::sort(l1.begin(), l1.end());
|
||||||
|
std::sort(l2.begin(), l2.end());
|
||||||
|
BOOST_TEST(l1 == l2);
|
||||||
|
}
|
||||||
|
|
||||||
|
UNORDERED_AUTO_TEST (pull_) {
|
||||||
|
#if defined(BOOST_UNORDERED_FOA_TESTS)
|
||||||
|
test_pull<
|
||||||
|
boost::unordered_flat_map<move_only_type, move_only_type> >();
|
||||||
|
test_pull<
|
||||||
|
boost::unordered_flat_set<move_only_type> >();
|
||||||
|
test_pull<
|
||||||
|
boost::unordered_node_map<move_only_type, move_only_type> >();
|
||||||
|
test_pull<
|
||||||
|
boost::unordered_node_set<move_only_type> >();
|
||||||
|
#else
|
||||||
|
// Closed-addressing containers do not provide pull
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
RUN_TESTS()
|
Loading…
x
Reference in New Issue
Block a user