Optimize emplace() for exactly a value_type or init_type argument (#227)

* Add structs to count special member functions

* Add failing emplace tests, that will pass after making the optimization

* Optimize emplace() to not allocate when we already have a value_type or init_type

* Fix newly failing cfoa tests
This commit is contained in:
Braden Ganetsky
2023-12-31 11:56:14 -06:00
committed by GitHub
parent 75a94781d5
commit 67c5cdb3a6
10 changed files with 418 additions and 37 deletions
@@ -28,6 +28,7 @@
#include <boost/unordered/detail/foa/tuple_rotate_right.hpp>
#include <boost/unordered/detail/serialization_version.hpp>
#include <boost/unordered/detail/static_assert.hpp>
#include <boost/unordered/detail/type_traits.hpp>
#include <cstddef>
#include <functional>
#include <initializer_list>
@@ -682,6 +683,14 @@ public:
return construct_and_emplace(std::forward<Args>(args)...);
}
/* Optimization for value_type and init_type, to avoid constructing twice */
template<typename Value>
BOOST_FORCEINLINE auto emplace(Value&& x)->typename std::enable_if<
detail::is_similar_to_any<Value,value_type,init_type>::value,bool>::type
{
return emplace_impl(std::forward<Value>(x));
}
BOOST_FORCEINLINE bool
insert(const init_type& x){return emplace_impl(x);}
@@ -18,6 +18,7 @@
#include <boost/core/serialization.hpp>
#include <boost/unordered/detail/foa/core.hpp>
#include <boost/unordered/detail/serialize_tracked_address.hpp>
#include <boost/unordered/detail/type_traits.hpp>
#include <cstddef>
#include <iterator>
#include <memory>
@@ -405,6 +406,16 @@ public:
return emplace_impl(type_policy::move(x.value()));
}
/* Optimization for value_type and init_type, to avoid constructing twice */
template <typename T>
BOOST_FORCEINLINE typename std::enable_if<
detail::is_similar_to_any<T, value_type, init_type>::value,
std::pair<iterator, bool> >::type
emplace(T&& x)
{
return emplace_impl(std::forward<T>(x));
}
template<typename Key,typename... Args>
BOOST_FORCEINLINE std::pair<iterator,bool> try_emplace(
Key&& x,Args&&... args)
@@ -147,6 +147,23 @@ namespace boost {
!std::is_convertible<Key, const_iterator>::value;
};
template <class T>
using remove_cvref_t =
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
template <class T, class U>
using is_similar = std::is_same<remove_cvref_t<T>, remove_cvref_t<U> >;
template <class, class...> struct is_similar_to_any : std::false_type
{
};
template <class T, class U, class... Us>
struct is_similar_to_any<T, U, Us...>
: std::conditional<is_similar<T, U>::value, is_similar<T, U>,
is_similar_to_any<T, Us...> >::type
{
};
#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
// https://eel.is/c++draft/container.requirements#container.alloc.reqmts-34
// https://eel.is/c++draft/container.requirements#unord.req.general-243