mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-29 19:07:15 +02:00
Optimize emplace(k,v) for foa and cfoa containers
This commit is contained in:
@ -691,6 +691,18 @@ public:
|
||||
return emplace_impl(std::forward<Value>(x));
|
||||
}
|
||||
|
||||
/* Optimizations for maps for (k,v) to avoid eagerly constructing value */
|
||||
template <typename K, typename V>
|
||||
BOOST_FORCEINLINE auto emplace(K&& k, V&& v) ->
|
||||
typename std::enable_if<is_emplace_kv_able<concurrent_table, K>::value,
|
||||
bool>::type
|
||||
{
|
||||
alloc_cted_or_fwded_key_type<type_policy, Allocator, K&&> x(
|
||||
this->al(), std::forward<K>(k));
|
||||
return emplace_impl(
|
||||
try_emplace_args_t{}, x.move_or_fwd(), std::forward<V>(v));
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE bool
|
||||
insert(const init_type& x){return emplace_impl(x);}
|
||||
|
||||
|
@ -1232,6 +1232,58 @@ public:
|
||||
insert_type& value(){return val.value();}
|
||||
};
|
||||
|
||||
template<typename TypePolicy,typename Allocator,typename... Args>
|
||||
alloc_cted_insert_type<TypePolicy,Allocator,Args...>
|
||||
alloc_make_insert_type(const Allocator& al,Args&&... args)
|
||||
{
|
||||
return {al,std::forward<Args>(args)...};
|
||||
}
|
||||
|
||||
template <typename TypePolicy, typename Allocator, typename KFwdRef,
|
||||
typename = void>
|
||||
class alloc_cted_or_fwded_key_type
|
||||
{
|
||||
using key_type = typename TypePolicy::key_type;
|
||||
allocator_constructed<Allocator, key_type, TypePolicy> val;
|
||||
|
||||
public:
|
||||
alloc_cted_or_fwded_key_type(const Allocator& al_, KFwdRef k)
|
||||
: val(al_, std::forward<KFwdRef>(k))
|
||||
{
|
||||
}
|
||||
|
||||
key_type&& move_or_fwd() { return std::move(val.value()); }
|
||||
};
|
||||
|
||||
template <typename TypePolicy, typename Allocator, typename KFwdRef>
|
||||
class alloc_cted_or_fwded_key_type<TypePolicy, Allocator, KFwdRef,
|
||||
typename std::enable_if<
|
||||
is_similar<KFwdRef, typename TypePolicy::key_type>::value>::type>
|
||||
{
|
||||
// This specialization acts as a forwarding-reference wrapper
|
||||
BOOST_UNORDERED_STATIC_ASSERT(std::is_reference<KFwdRef>::value);
|
||||
KFwdRef ref;
|
||||
|
||||
public:
|
||||
alloc_cted_or_fwded_key_type(const Allocator&, KFwdRef k)
|
||||
: ref(std::forward<KFwdRef>(k))
|
||||
{
|
||||
}
|
||||
|
||||
KFwdRef move_or_fwd() { return std::forward<KFwdRef>(ref); }
|
||||
};
|
||||
|
||||
template <typename Container>
|
||||
using is_map =
|
||||
std::integral_constant<bool, !std::is_same<typename Container::key_type,
|
||||
typename Container::value_type>::value>;
|
||||
|
||||
template <typename Container, typename K>
|
||||
using is_emplace_kv_able = std::integral_constant<bool,
|
||||
is_map<Container>::value &&
|
||||
(is_similar<K, typename Container::key_type>::value ||
|
||||
is_complete_and_move_constructible<typename Container::key_type>::value)>;
|
||||
|
||||
/* table_core. The TypePolicy template parameter is used to generate
|
||||
* instantiations suitable for either maps or sets, and introduces non-standard
|
||||
* init_type and element_type:
|
||||
@ -1249,7 +1301,7 @@ public:
|
||||
*
|
||||
* - TypePolicy::construct and TypePolicy::destroy are used for the
|
||||
* construction and destruction of the internal types: value_type,
|
||||
* init_type and element_type.
|
||||
* init_type, element_type, and key_type.
|
||||
*
|
||||
* - TypePolicy::move is used to provide move semantics for the internal
|
||||
* types used by the container during rehashing and emplace. These types
|
||||
|
@ -56,6 +56,12 @@ namespace boost {
|
||||
boost::allocator_construct(al, p, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class A, class... Args>
|
||||
static void construct(A& al, key_type* p, Args&&... args)
|
||||
{
|
||||
boost::allocator_construct(al, p, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class A> static void destroy(A& al, init_type* p) noexcept
|
||||
{
|
||||
boost::allocator_destroy(al, p);
|
||||
@ -65,6 +71,11 @@ namespace boost {
|
||||
{
|
||||
boost::allocator_destroy(al, p);
|
||||
}
|
||||
|
||||
template <class A> static void destroy(A& al, key_type* p) noexcept
|
||||
{
|
||||
boost::allocator_destroy(al, p);
|
||||
}
|
||||
};
|
||||
} // namespace foa
|
||||
} // namespace detail
|
||||
|
@ -82,6 +82,12 @@ namespace boost {
|
||||
boost::allocator_construct(al, p, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class A, class... Args>
|
||||
static void construct(A& al, key_type* p, Args&&... args)
|
||||
{
|
||||
boost::allocator_construct(al, p, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class A, class... Args>
|
||||
static void construct(A& al, element_type* p, Args&&... args)
|
||||
{
|
||||
@ -109,6 +115,11 @@ namespace boost {
|
||||
boost::allocator_destroy(al, p);
|
||||
}
|
||||
|
||||
template <class A> static void destroy(A& al, key_type* p) noexcept
|
||||
{
|
||||
boost::allocator_destroy(al, p);
|
||||
}
|
||||
|
||||
template <class A>
|
||||
static void destroy(A& al, element_type* p) noexcept
|
||||
{
|
||||
|
@ -416,6 +416,19 @@ public:
|
||||
return emplace_impl(std::forward<T>(x));
|
||||
}
|
||||
|
||||
/* Optimizations for maps for (k,v) to avoid eagerly constructing value */
|
||||
template <typename K, typename V>
|
||||
BOOST_FORCEINLINE
|
||||
typename std::enable_if<is_emplace_kv_able<table, K>::value,
|
||||
std::pair<iterator, bool> >::type
|
||||
emplace(K&& k, V&& v)
|
||||
{
|
||||
alloc_cted_or_fwded_key_type<type_policy, Allocator, K&&> x(
|
||||
this->al(), std::forward<K>(k));
|
||||
return emplace_impl(
|
||||
try_emplace_args_t{}, x.move_or_fwd(), std::forward<V>(v));
|
||||
}
|
||||
|
||||
template<typename Key,typename... Args>
|
||||
BOOST_FORCEINLINE std::pair<iterator,bool> try_emplace(
|
||||
Key&& x,Args&&... args)
|
||||
|
@ -48,6 +48,20 @@ namespace boost {
|
||||
|
||||
template <typename... Ts> using void_t = typename make_void<Ts...>::type;
|
||||
|
||||
template <class T, class = void> struct is_complete : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_complete<T, void_t<int[sizeof(T)]> > : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
using is_complete_and_move_constructible =
|
||||
typename std::conditional<is_complete<T>::value,
|
||||
std::is_move_constructible<T>, std::false_type>::type;
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION, < 50000)
|
||||
/* std::is_trivially_default_constructible not provided */
|
||||
template <class T>
|
||||
|
Reference in New Issue
Block a user