Merge pull request #177 from cmazakas/feature/p2363

Feature/p2363
This commit is contained in:
Christian Mazakas
2022-12-20 10:55:20 -08:00
committed by GitHub
14 changed files with 1086 additions and 184 deletions

View File

@@ -1477,7 +1477,22 @@ namespace boost {
}
#endif
}
template <typename T, typename Alloc, typename Key>
inline typename boost::allocator_pointer<Alloc>::type
construct_node_from_key(T*, Alloc& alloc, BOOST_FWD_REF(Key) k)
{
return construct_node(alloc, boost::forward<Key>(k));
}
template <typename T, typename V, typename Alloc, typename Key>
inline typename boost::allocator_pointer<Alloc>::type
construct_node_from_key(
std::pair<T const, V>*, Alloc& alloc, BOOST_FWD_REF(Key) k)
{
return construct_node_pair(alloc, boost::forward<Key>(k));
}
} // namespace func
}
}
}
@@ -2640,8 +2655,10 @@ namespace boost {
} else {
node_allocator_type alloc = node_alloc();
node_tmp tmp(
detail::func::construct_node_pair(alloc, boost::forward<Key>(k)),
value_type* dispatch = BOOST_NULLPTR;
node_tmp tmp(detail::func::construct_node_from_key(
dispatch, alloc, boost::forward<Key>(k)),
alloc);
if (size_ + 1 > max_load_) {
@@ -2660,7 +2677,7 @@ namespace boost {
template <typename Key>
iterator try_emplace_hint_unique(c_iterator hint, BOOST_FWD_REF(Key) k)
{
if (hint.p && this->key_eq()(hint->first, k)) {
if (hint.p && this->key_eq()(extractor::extract(*hint), k)) {
return iterator(hint.p, hint.itb);
} else {
return try_emplace_unique(k).first;

View File

@@ -53,10 +53,10 @@ namespace boost {
{
};
template <class, class A, class B> struct are_transparent
template <class, class Hash, class KeyEqual> struct are_transparent
{
static bool const value =
is_transparent<A>::value && is_transparent<B>::value;
is_transparent<Hash>::value && is_transparent<KeyEqual>::value;
};
template <class Key, class UnorderedMap> struct transparent_non_iterable

View File

@@ -278,24 +278,37 @@ namespace boost {
template <class M>
std::pair<iterator, bool> insert_or_assign(key_type const& key, M&& obj)
{
auto iter_bool_pair = table_.try_emplace(key, std::forward<M>(obj));
if (iter_bool_pair.second) {
return iter_bool_pair;
auto ibp = table_.try_emplace(key, std::forward<M>(obj));
if (ibp.second) {
return ibp;
}
iter_bool_pair.first->second = std::forward<M>(obj);
return iter_bool_pair;
ibp.first->second = std::forward<M>(obj);
return ibp;
}
template <class M>
std::pair<iterator, bool> insert_or_assign(key_type&& key, M&& obj)
{
auto iter_bool_pair =
table_.try_emplace(std::move(key), std::forward<M>(obj));
if (iter_bool_pair.second) {
return iter_bool_pair;
auto ibp = table_.try_emplace(std::move(key), std::forward<M>(obj));
if (ibp.second) {
return ibp;
}
iter_bool_pair.first->second = std::forward<M>(obj);
return iter_bool_pair;
ibp.first->second = std::forward<M>(obj);
return ibp;
}
template <class K, class M>
typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
std::pair<iterator, bool> >::type
insert_or_assign(K&& k, M&& obj)
{
auto ibp = table_.try_emplace(std::forward<K>(k), std::forward<M>(obj));
if (ibp.second) {
return ibp;
}
ibp.first->second = std::forward<M>(obj);
return ibp;
}
template <class M>
@@ -311,6 +324,16 @@ namespace boost {
.first;
}
template <class K, class M>
typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
iterator>::type
insert_or_assign(const_iterator, K&& k, M&& obj)
{
return this->insert_or_assign(std::forward<K>(k), std::forward<M>(obj))
.first;
}
template <class... Args>
BOOST_FORCEINLINE std::pair<iterator, bool> emplace(Args&&... args)
{
@@ -337,6 +360,17 @@ namespace boost {
return table_.try_emplace(std::move(key), std::forward<Args>(args)...);
}
template <class K, class... Args>
BOOST_FORCEINLINE typename std::enable_if<
boost::unordered::detail::transparent_non_iterable<K,
unordered_flat_map>::value,
std::pair<iterator, bool> >::type
try_emplace(K&& key, Args&&... args)
{
return table_.try_emplace(
std::forward<K>(key), std::forward<Args>(args)...);
}
template <class... Args>
BOOST_FORCEINLINE iterator try_emplace(
const_iterator, key_type const& key, Args&&... args)
@@ -352,6 +386,18 @@ namespace boost {
.first;
}
template <class K, class... Args>
BOOST_FORCEINLINE typename std::enable_if<
boost::unordered::detail::transparent_non_iterable<K,
unordered_flat_map>::value,
iterator>::type
try_emplace(const_iterator, K&& key, Args&&... args)
{
return table_
.try_emplace(std::forward<K>(key), std::forward<Args>(args)...)
.first;
}
BOOST_FORCEINLINE void erase(iterator pos) { table_.erase(pos); }
BOOST_FORCEINLINE void erase(const_iterator pos)
{
@@ -427,6 +473,34 @@ namespace boost {
std::out_of_range("key was not found in unordered_flat_map"));
}
template <class K>
typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
mapped_type&>::type
at(K&& key)
{
auto pos = table_.find(std::forward<K>(key));
if (pos != table_.end()) {
return pos->second;
}
boost::throw_exception(
std::out_of_range("key was not found in unordered_flat_map"));
}
template <class K>
typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
mapped_type const&>::type
at(K&& key) const
{
auto pos = table_.find(std::forward<K>(key));
if (pos != table_.end()) {
return pos->second;
}
boost::throw_exception(
std::out_of_range("key was not found in unordered_flat_map"));
}
BOOST_FORCEINLINE mapped_type& operator[](key_type const& key)
{
return table_.try_emplace(key).first->second;
@@ -437,6 +511,15 @@ namespace boost {
return table_.try_emplace(std::move(key)).first->second;
}
template <class K>
typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
mapped_type&>::type
operator[](K&& key)
{
return table_.try_emplace(std::forward<K>(key)).first->second;
}
BOOST_FORCEINLINE size_type count(key_type const& key) const
{
auto pos = table_.find(key);

View File

@@ -231,6 +231,15 @@ namespace boost {
return table_.insert(std::move(value));
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
detail::transparent_non_iterable<K, unordered_flat_set>::value,
std::pair<iterator, bool> >::type
insert(K&& k)
{
return table_.try_emplace(std::forward<K>(k));
}
BOOST_FORCEINLINE iterator insert(const_iterator, value_type const& value)
{
return table_.insert(value).first;
@@ -241,6 +250,15 @@ namespace boost {
return table_.insert(std::move(value)).first;
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
detail::transparent_non_iterable<K, unordered_flat_set>::value,
iterator>::type
insert(const_iterator, K&& k)
{
return table_.try_emplace(std::forward<K>(k)).first;
}
template <class InputIterator>
void insert(InputIterator first, InputIterator last)
{

View File

@@ -486,6 +486,16 @@ namespace boost {
boost::move(k), boost::forward<Args>(args)...);
}
template <class Key, class... Args>
typename boost::enable_if_c<
detail::transparent_non_iterable<Key, unordered_map>::value,
std::pair<iterator, bool> >::type
try_emplace(Key&& k, Args&&... args)
{
return table_.try_emplace_unique(
boost::forward<Key>(k), boost::forward<Args>(args)...);
}
template <class... Args>
iterator try_emplace(
const_iterator hint, key_type const& k, BOOST_FWD_REF(Args)... args)
@@ -502,6 +512,16 @@ namespace boost {
hint, boost::move(k), boost::forward<Args>(args)...);
}
template <class Key, class... Args>
typename boost::enable_if_c<
detail::transparent_non_iterable<Key, unordered_map>::value,
iterator>::type
try_emplace(const_iterator hint, Key&& k, Args&&... args)
{
return table_.try_emplace_hint_unique(
hint, boost::forward<Key>(k), boost::forward<Args>(args)...);
}
#else
// In order to make this a template, this handles both:
@@ -582,6 +602,43 @@ namespace boost {
boost::forward<A1>(a1), boost::forward<A2>(a2)));
}
// try_emplace(Key&&, Args&&...)
template <typename Key, typename A0>
typename boost::enable_if_c<
detail::transparent_non_iterable<Key, unordered_map>::value,
std::pair<iterator, bool> >::type
try_emplace(BOOST_FWD_REF(Key) k, BOOST_FWD_REF(A0) a0)
{
return table_.try_emplace_unique(
boost::forward<Key>(k), boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0)));
}
template <typename Key, typename A0, typename A1>
typename boost::enable_if_c<
detail::transparent_non_iterable<Key, unordered_map>::value,
std::pair<iterator, bool> >::type
try_emplace(
BOOST_FWD_REF(Key) k, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{
return table_.try_emplace_unique(boost::forward<Key>(k),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)));
}
template <typename Key, typename A0, typename A1, typename A2>
typename boost::enable_if_c<
detail::transparent_non_iterable<Key, unordered_map>::value,
std::pair<iterator, bool> >::type
try_emplace(BOOST_FWD_REF(Key) k, BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
return table_.try_emplace_unique(boost::forward<Key>(k),
boost::unordered::detail::create_emplace_args(boost::forward<A0>(a0),
boost::forward<A1>(a1), boost::forward<A2>(a2)));
}
// try_emplace(const_iterator hint, key const&, Args&&...)
template <typename A0>
@@ -640,6 +697,44 @@ namespace boost {
boost::forward<A1>(a1), boost::forward<A2>(a2)));
}
// try_emplace(const_iterator hint, Key&&, Args&&...)
template <typename Key, typename A0>
typename boost::enable_if_c<
detail::transparent_non_iterable<Key, unordered_map>::value,
iterator>::type
try_emplace(
const_iterator hint, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(A0) a0)
{
return table_.try_emplace_hint_unique(hint, boost::forward<Key>(k),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0)));
}
template <typename Key, typename A0, typename A1>
typename boost::enable_if_c<
detail::transparent_non_iterable<Key, unordered_map>::value,
iterator>::type
try_emplace(const_iterator hint, BOOST_FWD_REF(Key) k,
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1)
{
return table_.try_emplace_hint_unique(hint, boost::forward<Key>(k),
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0), boost::forward<A1>(a1)));
}
template <typename Key, typename A0, typename A1, typename A2>
typename boost::enable_if_c<
detail::transparent_non_iterable<Key, unordered_map>::value,
iterator>::type
try_emplace(const_iterator hint, BOOST_FWD_REF(Key) k,
BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
return table_.try_emplace_hint_unique(hint, boost::forward<Key>(k),
boost::unordered::detail::create_emplace_args(boost::forward<A0>(a0),
boost::forward<A1>(a1), boost::forward<A2>(a2)));
}
#define BOOST_UNORDERED_TRY_EMPLACE(z, n, _) \
\
template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
@@ -706,6 +801,15 @@ namespace boost {
boost::move(k), boost::forward<M>(obj));
}
template <class Key, class M>
typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
std::pair<iterator, bool> >::type
insert_or_assign(BOOST_FWD_REF(Key) k, BOOST_FWD_REF(M) obj)
{
return table_.insert_or_assign_unique(
boost::forward<Key>(k), boost::forward<M>(obj));
}
template <class M>
iterator insert_or_assign(
const_iterator, key_type const& k, BOOST_FWD_REF(M) obj)
@@ -722,6 +826,18 @@ namespace boost {
.first;
}
template <class Key, class M>
typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
iterator>::type
insert_or_assign(
const_iterator, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(M) obj)
{
return table_
.insert_or_assign_unique(
boost::forward<Key>(k), boost::forward<M>(obj))
.first;
}
iterator erase(iterator);
iterator erase(const_iterator);
size_type erase(const key_type&);
@@ -856,9 +972,23 @@ namespace boost {
mapped_type& operator[](const key_type&);
mapped_type& operator[](BOOST_RV_REF(key_type));
template <class Key>
typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
mapped_type&>::type
operator[](BOOST_FWD_REF(Key) k);
mapped_type& at(const key_type&);
mapped_type const& at(const key_type&) const;
template <class Key>
typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
mapped_type&>::type at(BOOST_FWD_REF(Key) k);
template <class Key>
typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
mapped_type const&>::type at(BOOST_FWD_REF(Key) k) const;
// bucket interface
size_type bucket_count() const BOOST_NOEXCEPT
@@ -878,6 +1008,14 @@ namespace boost {
return table_.hash_to_bucket(table_.hash(k));
}
template <class Key>
typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
size_type>::type
bucket(BOOST_FWD_REF(Key) k) const
{
return table_.hash_to_bucket(table_.hash(boost::forward<Key>(k)));
}
local_iterator begin(size_type n)
{
return table_.begin(n);
@@ -1584,6 +1722,14 @@ namespace boost {
return table_.hash_to_bucket(table_.hash(k));
}
template <class Key>
typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
size_type>::type
bucket(BOOST_FWD_REF(Key) k) const
{
return table_.hash_to_bucket(table_.hash(boost::forward<Key>(k)));
}
local_iterator begin(size_type n)
{
return local_iterator(table_.begin(n));
@@ -2098,6 +2244,15 @@ namespace boost {
return table_.try_emplace_unique(boost::move(k)).first->second;
}
template <class K, class T, class H, class P, class A>
template <class Key>
typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
typename unordered_map<K, T, H, P, A>::mapped_type&>::type
unordered_map<K, T, H, P, A>::operator[](BOOST_FWD_REF(Key) k)
{
return table_.try_emplace_unique(boost::forward<Key>(k)).first->second;
}
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>::at(const key_type& k)
@@ -2130,6 +2285,42 @@ namespace boost {
std::out_of_range("Unable to find key in unordered_map."));
}
template <class K, class T, class H, class P, class A>
template <class Key>
typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
typename unordered_map<K, T, H, P, A>::mapped_type&>::type
unordered_map<K, T, H, P, A>::at(BOOST_FWD_REF(Key) k)
{
typedef typename table::node_pointer node_pointer;
if (table_.size_) {
node_pointer p = table_.find_node(boost::forward<Key>(k));
if (p)
return p->value().second;
}
boost::throw_exception(
std::out_of_range("Unable to find key in unordered_map."));
}
template <class K, class T, class H, class P, class A>
template <class Key>
typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
typename unordered_map<K, T, H, P, A>::mapped_type const&>::type
unordered_map<K, T, H, P, A>::at(BOOST_FWD_REF(Key) k) const
{
typedef typename table::node_pointer node_pointer;
if (table_.size_) {
node_pointer p = table_.find_node(boost::forward<Key>(k));
if (p)
return p->value().second;
}
boost::throw_exception(
std::out_of_range("Unable to find key in unordered_map."));
}
template <class K, class T, class H, class P, class A>
typename unordered_map<K, T, H, P, A>::size_type
unordered_map<K, T, H, P, A>::bucket_size(size_type n) const

View File

@@ -390,6 +390,15 @@ namespace boost {
return this->emplace(boost::move(x));
}
template <class Key>
typename boost::enable_if_c<
detail::transparent_non_iterable<Key, unordered_set>::value,
std::pair<iterator, bool> >::type
insert(BOOST_FWD_REF(Key) k)
{
return table_.try_emplace_unique(boost::forward<Key>(k));
}
iterator insert(const_iterator hint, value_type const& x)
{
return this->emplace_hint(hint, x);
@@ -400,6 +409,15 @@ namespace boost {
return this->emplace_hint(hint, boost::move(x));
}
template <class Key>
typename boost::enable_if_c<
detail::transparent_non_iterable<Key, unordered_set>::value,
iterator>::type
insert(const_iterator hint, BOOST_FWD_REF(Key) k)
{
return table_.try_emplace_hint_unique(hint, boost::forward<Key>(k));
}
template <class InputIt> void insert(InputIt, InputIt);
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@@ -571,6 +589,14 @@ namespace boost {
return table_.hash_to_bucket(table_.hash(k));
}
template <class Key>
typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
size_type>::type
bucket(BOOST_FWD_REF(Key) k) const
{
return table_.hash_to_bucket(table_.hash(boost::forward<Key>(k)));
}
local_iterator begin(size_type n)
{
return local_iterator(table_.begin(n));
@@ -1212,6 +1238,14 @@ namespace boost {
return table_.hash_to_bucket(table_.hash(k));
}
template <class Key>
typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
size_type>::type
bucket(BOOST_FWD_REF(Key) k) const
{
return table_.hash_to_bucket(table_.hash(boost::forward<Key>(k)));
}
local_iterator begin(size_type n)
{
return local_iterator(table_.begin(n));