From 7ce7ef50504451c4542bc1d509182e4777afa825 Mon Sep 17 00:00:00 2001 From: Christian Mazakas Date: Wed, 11 Jan 2023 14:37:45 -0800 Subject: [PATCH] Add moved_value_from() to container policies, enabling proper move semantics for node-based containers in the case of unequal allocators --- include/boost/unordered/detail/foa.hpp | 4 ++-- include/boost/unordered/unordered_flat_map.hpp | 5 +++++ include/boost/unordered/unordered_flat_set.hpp | 5 +++++ include/boost/unordered/unordered_node_map.hpp | 12 ++++++++++++ include/boost/unordered/unordered_node_set.hpp | 5 +++++ 5 files changed, 29 insertions(+), 2 deletions(-) diff --git a/include/boost/unordered/detail/foa.hpp b/include/boost/unordered/detail/foa.hpp index 5cc61a60..2305c5ea 100644 --- a/include/boost/unordered/detail/foa.hpp +++ b/include/boost/unordered/detail/foa.hpp @@ -1255,7 +1255,7 @@ public: * elements' values. */ x.for_all_elements([this](element_type* p){ - unchecked_insert(type_policy::move(*p)); + unchecked_insert(type_policy::moved_value_from(*p)); }); } } @@ -1352,7 +1352,7 @@ public: * elements' values. */ x.for_all_elements([this](element_type* p){ - unchecked_insert(type_policy::move(*p)); + unchecked_insert(type_policy::moved_value_from(*p)); }); } } diff --git a/include/boost/unordered/unordered_flat_map.hpp b/include/boost/unordered/unordered_flat_map.hpp index 7ceebc40..c9b9f544 100644 --- a/include/boost/unordered/unordered_flat_map.hpp +++ b/include/boost/unordered/unordered_flat_map.hpp @@ -60,6 +60,11 @@ namespace boost { std::move(const_cast(x.second))}; } + static moved_type moved_value_from(element_type& x) + { + return move(x); + } + template static void construct(A& al, element_type* p, moved_type&& x) { diff --git a/include/boost/unordered/unordered_flat_set.hpp b/include/boost/unordered/unordered_flat_set.hpp index ca3c5a43..b2b91db5 100644 --- a/include/boost/unordered/unordered_flat_set.hpp +++ b/include/boost/unordered/unordered_flat_set.hpp @@ -45,6 +45,11 @@ namespace boost { static element_type&& move(element_type& x) { return std::move(x); } + static element_type&& moved_value_from(element_type& x) + { + return move(x); + } + template static void construct(A& al, element_type* p, element_type const& copy) { diff --git a/include/boost/unordered/unordered_node_map.hpp b/include/boost/unordered/unordered_node_map.hpp index d31b824e..85e7bab1 100644 --- a/include/boost/unordered/unordered_node_map.hpp +++ b/include/boost/unordered/unordered_node_map.hpp @@ -46,12 +46,24 @@ namespace boost { { value_type* p; + /* + * we use a defined copy constructor here so the type is no longer + * trivially copy-constructible which inhibits our memcpy + * optimizations when copying the tables + */ element_type() : p(nullptr) {} element_type(element_type const& rhs) : p(rhs.p) {} }; static value_type& value_from(element_type x) { return *(x.p); } + static std::pair moved_value_from( + element_type& x) + { + return {std::move(const_cast(x.p->first)), + std::move(const_cast(x.p->second))}; + } + template static raw_key_type const& extract(std::pair const& kv) { diff --git a/include/boost/unordered/unordered_node_set.hpp b/include/boost/unordered/unordered_node_set.hpp index 5457f40f..4a9b5b12 100644 --- a/include/boost/unordered/unordered_node_set.hpp +++ b/include/boost/unordered/unordered_node_set.hpp @@ -57,6 +57,11 @@ namespace boost { static Key const& extract(element_type k) { return *k.p; } static element_type&& move(element_type& x) { return std::move(x); } + static value_type&& moved_value_from(element_type& x) + { + return std::move(*x.p); + } + template static void construct(A& al, element_type* p, element_type const& copy) {