forked from boostorg/unordered
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));
|
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
|
BOOST_FORCEINLINE bool
|
||||||
insert(const init_type& x){return emplace_impl(x);}
|
insert(const init_type& x){return emplace_impl(x);}
|
||||||
|
|
||||||
|
@ -1232,6 +1232,58 @@ public:
|
|||||||
insert_type& value(){return val.value();}
|
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
|
/* table_core. The TypePolicy template parameter is used to generate
|
||||||
* instantiations suitable for either maps or sets, and introduces non-standard
|
* instantiations suitable for either maps or sets, and introduces non-standard
|
||||||
* init_type and element_type:
|
* init_type and element_type:
|
||||||
@ -1249,7 +1301,7 @@ public:
|
|||||||
*
|
*
|
||||||
* - TypePolicy::construct and TypePolicy::destroy are used for the
|
* - TypePolicy::construct and TypePolicy::destroy are used for the
|
||||||
* construction and destruction of the internal types: value_type,
|
* 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
|
* - TypePolicy::move is used to provide move semantics for the internal
|
||||||
* types used by the container during rehashing and emplace. These types
|
* 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)...);
|
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
|
template <class A> static void destroy(A& al, init_type* p) noexcept
|
||||||
{
|
{
|
||||||
boost::allocator_destroy(al, p);
|
boost::allocator_destroy(al, p);
|
||||||
@ -65,6 +71,11 @@ namespace boost {
|
|||||||
{
|
{
|
||||||
boost::allocator_destroy(al, p);
|
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 foa
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
@ -82,6 +82,12 @@ namespace boost {
|
|||||||
boost::allocator_construct(al, p, std::forward<Args>(args)...);
|
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>
|
template <class A, class... Args>
|
||||||
static void construct(A& al, element_type* p, Args&&... args)
|
static void construct(A& al, element_type* p, Args&&... args)
|
||||||
{
|
{
|
||||||
@ -109,6 +115,11 @@ namespace boost {
|
|||||||
boost::allocator_destroy(al, p);
|
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>
|
template <class A>
|
||||||
static void destroy(A& al, element_type* p) noexcept
|
static void destroy(A& al, element_type* p) noexcept
|
||||||
{
|
{
|
||||||
|
@ -416,6 +416,19 @@ public:
|
|||||||
return emplace_impl(std::forward<T>(x));
|
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>
|
template<typename Key,typename... Args>
|
||||||
BOOST_FORCEINLINE std::pair<iterator,bool> try_emplace(
|
BOOST_FORCEINLINE std::pair<iterator,bool> try_emplace(
|
||||||
Key&& x,Args&&... args)
|
Key&& x,Args&&... args)
|
||||||
|
@ -48,6 +48,20 @@ namespace boost {
|
|||||||
|
|
||||||
template <typename... Ts> using void_t = typename make_void<Ts...>::type;
|
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)
|
#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION, < 50000)
|
||||||
/* std::is_trivially_default_constructible not provided */
|
/* std::is_trivially_default_constructible not provided */
|
||||||
template <class T>
|
template <class T>
|
||||||
|
Reference in New Issue
Block a user