Implement try_emplace

This commit is contained in:
Daniel James
2017-02-27 03:59:02 +00:00
parent 958d206bb6
commit 5f5f8ef1e4
5 changed files with 527 additions and 17 deletions

View File

@@ -1721,6 +1721,35 @@ construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m)
BOOST_CATCH_END
return a.release();
}
template <typename Alloc, typename Key, BOOST_UNORDERED_EMPLACE_TEMPLATE>
inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
construct_node_pair_from_args(
Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_UNORDERED_EMPLACE_ARGS)
{
node_constructor<Alloc> a(alloc);
a.create_node();
boost::unordered::detail::func::call_construct(
alloc, boost::unordered::detail::func::const_cast_pointer(
boost::addressof(a.node_->value_ptr()->first)),
boost::forward<Key>(k));
BOOST_TRY
{
boost::unordered::detail::func::construct_from_args(
alloc, boost::unordered::detail::func::const_cast_pointer(
boost::addressof(a.node_->value_ptr()->second)),
BOOST_UNORDERED_EMPLACE_FORWARD);
}
BOOST_CATCH(...)
{
boost::unordered::detail::func::call_destroy(
alloc, boost::unordered::detail::func::const_cast_pointer(
boost::addressof(a.node_->value_ptr()->first)));
BOOST_RETHROW;
}
BOOST_CATCH_END
return a.release();
}
}
}
}
@@ -3547,22 +3576,6 @@ struct table_impl : boost::unordered::detail::table<Types>
return this->add_node(b.release(), key_hash);
}
value_type& operator[](const_key_type& k)
{
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
if (pos) {
return pos->value();
} else {
return this
->resize_and_add_node(
boost::unordered::detail::func::construct_node_pair(
this->node_alloc(), k),
key_hash)
->value();
}
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
emplace_return emplace(boost::unordered::detail::emplace_args1<
@@ -3704,6 +3717,64 @@ struct table_impl : boost::unordered::detail::table<Types>
}
}
template <typename Key>
emplace_return try_emplace_impl(BOOST_FWD_REF(Key) k)
{
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
if (pos) {
return emplace_return(iterator(pos), false);
} else {
return emplace_return(
iterator(this->resize_and_add_node(
boost::unordered::detail::func::construct_node_pair(
this->node_alloc(), boost::forward<Key>(k)),
key_hash)),
true);
}
}
template <typename Key>
iterator try_emplace_hint_impl(c_iterator hint, BOOST_FWD_REF(Key) k)
{
if (hint.node_ && this->key_eq()(hint->first, k)) {
return iterator(hint.node_);
} else {
return try_emplace_impl(k).first;
}
}
template <typename Key, BOOST_UNORDERED_EMPLACE_TEMPLATE>
emplace_return try_emplace_impl(
BOOST_FWD_REF(Key) k, BOOST_UNORDERED_EMPLACE_ARGS)
{
std::size_t key_hash = this->hash(k);
node_pointer pos = this->find_node(key_hash, k);
if (pos) {
return emplace_return(iterator(pos), false);
} else {
return emplace_return(
iterator(this->resize_and_add_node(
boost::unordered::detail::func::
construct_node_pair_from_args(this->node_alloc(),
boost::forward<Key>(k),
BOOST_UNORDERED_EMPLACE_FORWARD),
key_hash)),
true);
}
}
template <typename Key, BOOST_UNORDERED_EMPLACE_TEMPLATE>
iterator try_emplace_hint_impl(
c_iterator hint, BOOST_FWD_REF(Key) k, BOOST_UNORDERED_EMPLACE_ARGS)
{
if (hint.node_ && this->key_eq()(hint->first, k)) {
return iterator(hint.node_);
} else {
return try_emplace_impl(k, BOOST_UNORDERED_EMPLACE_FORWARD).first;
}
}
template <typename Key, typename M>
emplace_return insert_or_assign_impl(
BOOST_FWD_REF(Key) k, BOOST_FWD_REF(M) obj)

View File

@@ -220,6 +220,37 @@ template <class K, class T, class H, class P, class A> class unordered_map
{
return table_.emplace_hint(hint, boost::forward<Args>(args)...);
}
template <class... Args>
std::pair<iterator, bool> try_emplace(
key_type const& k, BOOST_FWD_REF(Args)... args)
{
return table_.try_emplace_impl(k, boost::forward<Args>(args)...);
}
template <class... Args>
iterator try_emplace(
const_iterator hint, key_type const& k, BOOST_FWD_REF(Args)... args)
{
return table_.try_emplace_hint_impl(
hint, k, boost::forward<Args>(args)...);
}
template <class... Args>
std::pair<iterator, bool> try_emplace(
BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
{
return table_.try_emplace_impl(
boost::move(k), boost::forward<Args>(args)...);
}
template <class... Args>
iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k,
BOOST_FWD_REF(Args)... args)
{
return table_.try_emplace_hint_impl(
hint, boost::move(k), boost::forward<Args>(args)...);
}
#else
#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
@@ -246,6 +277,18 @@ template <class K, class T, class H, class P, class A> class unordered_map
#endif
template <typename Key>
std::pair<iterator, bool> try_emplace(BOOST_FWD_REF(Key) k)
{
return table_.try_emplace_impl(boost::forward<Key>(k));
}
template <typename Key>
iterator try_emplace(const_iterator hint, BOOST_FWD_REF(Key) k)
{
return table_.try_emplace_hint_impl(hint, boost::forward<Key>(k));
}
template <typename A0>
std::pair<iterator, bool> emplace(BOOST_FWD_REF(A0) a0)
{
@@ -261,6 +304,39 @@ template <class K, class T, class H, class P, class A> class unordered_map
boost::forward<A0>(a0)));
}
template <typename A0>
std::pair<iterator, bool> try_emplace(
key_type const& k, BOOST_FWD_REF(A0) a0)
{
return table_.try_emplace_impl(
k, boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0)));
}
template <typename A0>
iterator try_emplace(
const_iterator hint, key_type const& k, BOOST_FWD_REF(A0) a0)
{
return table_.try_emplace_hint_impl(
hint, k, boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0)));
}
template <typename A0>
std::pair<iterator, bool> try_emplace(
BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0)
{
return table_.try_emplace_impl(boost::move(k), boost::forward<A0>(a0));
}
template <typename A0>
iterator try_emplace(
const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0)
{
return table_.try_emplace_hint_impl(
hint, boost::move(k), boost::forward<A0>(a0));
}
template <typename A0, typename A1>
std::pair<iterator, bool> emplace(
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
@@ -278,6 +354,44 @@ template <class K, class T, class H, class P, class A> class unordered_map
boost::forward<A0>(a0), boost::forward<A1>(a1)));
}
template <typename A0, typename A1>
std::pair<iterator, bool> try_emplace(
key_type const& k, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{
return table_.try_emplace_impl(
k, boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)));
}
template <typename A0, typename A1>
iterator try_emplace(const_iterator hint, key_type const& k,
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{
return table_.try_emplace_hint_impl(
hint, k, boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)));
}
template <typename A0, typename A1>
std::pair<iterator, bool> try_emplace(
BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{
return table_.try_emplace_impl(
boost::move(k),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)));
}
template <typename A0, typename A1>
iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k,
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{
return table_.try_emplace_hint_impl(
hint, boost::move(k),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)));
}
template <typename A0, typename A1, typename A2>
std::pair<iterator, bool> emplace(
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
@@ -297,6 +411,49 @@ template <class K, class T, class H, class P, class A> class unordered_map
boost::forward<A2>(a2)));
}
template <typename A0, typename A1, typename A2>
std::pair<iterator, bool> try_emplace(key_type const& k,
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
return table_.try_emplace_impl(
k, boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1),
boost::forward<A2>(a2)));
}
template <typename A0, typename A1, typename A2>
iterator try_emplace(const_iterator hint, key_type const& k,
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
return table_
.try_emplace_impl_(
hint, k, boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1),
boost::forward<A2>(a2)))
.first;
}
template <typename A0, typename A1, typename A2>
std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k,
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
return table_.try_emplace_impl(
boost::move(k), boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1),
boost::forward<A2>(a2)));
}
template <typename A0, typename A1, typename A2>
iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k,
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
return table_.try_emplace_hint_impl(
hint, boost::move(k),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1),
boost::forward<A2>(a2)));
}
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
std::pair<iterator, bool> emplace( \
@@ -313,6 +470,42 @@ template <class K, class T, class H, class P, class A> class unordered_map
return table_.emplace_hint( \
hint, boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \
} \
\
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
std::pair<iterator, bool> try_emplace( \
key_type const& k, BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \
return table_.try_emplace_impl( \
k, boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \
} \
\
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
iterator try_emplace(const_iterator hint, key_type const& k, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \
return table_.try_emplace_hint_impl(hint, k, \
boost::unordered::detail::create_emplace_args(BOOST_PP_ENUM_##z( \
n, BOOST_UNORDERED_CALL_FORWARD, a))); \
} \
\
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \
return table_.try_emplace_impl(boost::move(k), \
boost::unordered::detail::create_emplace_args(BOOST_PP_ENUM_##z( \
n, BOOST_UNORDERED_CALL_FORWARD, a))); \
} \
\
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \
{ \
return table_.try_emplace_hint_impl(hint, boost::move(k), \
boost::unordered::detail::create_emplace_args(BOOST_PP_ENUM_##z( \
n, BOOST_UNORDERED_CALL_FORWARD, a))); \
}
BOOST_PP_REPEAT_FROM_TO(
@@ -1114,7 +1307,7 @@ template <class K, class T, class H, class P, class A>
typename unordered_map<K, T, H, P, A>::mapped_type&
unordered_map<K, T, H, P, A>::operator[](const key_type& k)
{
return table_[k].second;
return table_.try_emplace_impl(k).first->second;
}
template <class K, class T, class H, class P, class A>