forked from boostorg/unordered
Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d689613172 | ||
|
|
8365ccb78a | ||
|
|
0a6da6979f | ||
|
|
31c33faf57 | ||
|
|
0d2751c5e1 | ||
|
|
f493603f5c | ||
|
|
74ca1b0e74 | ||
|
|
7b16324869 | ||
|
|
6680e86b38 |
+3
-6
@@ -3,7 +3,7 @@
|
|||||||
# Distributed under the Boost Software License, Version 1.0.
|
# Distributed under the Boost Software License, Version 1.0.
|
||||||
# https://www.boost.org/LICENSE_1_0.txt
|
# https://www.boost.org/LICENSE_1_0.txt
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.5...3.20)
|
cmake_minimum_required(VERSION 3.8...3.20)
|
||||||
|
|
||||||
project(boost_unordered VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
|
project(boost_unordered VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
|
||||||
|
|
||||||
@@ -18,16 +18,13 @@ target_link_libraries(boost_unordered
|
|||||||
Boost::config
|
Boost::config
|
||||||
Boost::container_hash
|
Boost::container_hash
|
||||||
Boost::core
|
Boost::core
|
||||||
Boost::move
|
|
||||||
Boost::mp11
|
Boost::mp11
|
||||||
Boost::predef
|
Boost::predef
|
||||||
Boost::preprocessor
|
|
||||||
Boost::static_assert
|
|
||||||
Boost::throw_exception
|
Boost::throw_exception
|
||||||
Boost::tuple
|
|
||||||
Boost::type_traits
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
target_compile_features(boost_unordered INTERFACE cxx_std_11)
|
||||||
|
|
||||||
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
|
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
|
||||||
|
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ Users can then declare a hash function `Hash` as avalanching either by embedding
|
|||||||
into the definition of `Hash`, or directly by specializing `hash_is_avalanching<Hash>` to a class with
|
into the definition of `Hash`, or directly by specializing `hash_is_avalanching<Hash>` to a class with
|
||||||
an embedded compile-time constant `value` set to `true`.
|
an embedded compile-time constant `value` set to `true`.
|
||||||
|
|
||||||
xref:unordered_flat_set[`boost::unordered_flat_set`] and xref:unordered_flat_map[`boost::unordered_flat_map`]
|
Open-addressing and concurrent containers
|
||||||
use the provided hash function `Hash` as-is if `hash_is_avalanching<Hash>::value` is `true`; otherwise, they
|
use the provided hash function `Hash` as-is if `hash_is_avalanching<Hash>::value` is `true`; otherwise, they
|
||||||
implement a bit-mixing post-processing stage to increase the quality of hashing at the expense of
|
implement a bit-mixing post-processing stage to increase the quality of hashing at the expense of
|
||||||
extra computational cost.
|
extra computational cost.
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ performing container-wide operations such as swapping or assignment.
|
|||||||
|
|
||||||
By using atomic operations to access the group metadata, lookup is (group-level)
|
By using atomic operations to access the group metadata, lookup is (group-level)
|
||||||
lock-free up to the point where an actual comparison needs to be done with an element
|
lock-free up to the point where an actual comparison needs to be done with an element
|
||||||
that has been previously SIMD-matched: only then it's the group's spinlock used.
|
that has been previously SIMD-matched: only then is the group's spinlock used.
|
||||||
|
|
||||||
Insertion uses the following _optimistic algorithm_:
|
Insertion uses the following _optimistic algorithm_:
|
||||||
|
|
||||||
|
|||||||
@@ -198,13 +198,13 @@ private:
|
|||||||
template<typename Integral>
|
template<typename Integral>
|
||||||
struct atomic_integral
|
struct atomic_integral
|
||||||
{
|
{
|
||||||
operator Integral()const{return n.load(std::memory_order_relaxed);}
|
operator Integral()const{return n.load(std::memory_order_acquire);}
|
||||||
void operator=(Integral m){n.store(m,std::memory_order_relaxed);}
|
void operator=(Integral m){n.store(m,std::memory_order_release);}
|
||||||
void operator|=(Integral m){n.fetch_or(m,std::memory_order_relaxed);}
|
void operator|=(Integral m){n.fetch_or(m);}
|
||||||
void operator&=(Integral m){n.fetch_and(m,std::memory_order_relaxed);}
|
void operator&=(Integral m){n.fetch_and(m);}
|
||||||
|
|
||||||
atomic_integral& operator=(atomic_integral const& rhs) {
|
atomic_integral& operator=(atomic_integral const& rhs) {
|
||||||
n.store(rhs.n.load(std::memory_order_relaxed),std::memory_order_relaxed);
|
n.store(rhs.n.load());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1177,7 +1177,7 @@ private:
|
|||||||
do{
|
do{
|
||||||
auto n=unchecked_countr_zero(mask);
|
auto n=unchecked_countr_zero(mask);
|
||||||
if(BOOST_LIKELY(
|
if(BOOST_LIKELY(
|
||||||
pg->is_occupied(n)&&bool(this->pred()(x,this->key_from(p[n]))))){
|
is_occupied(pg,n)&&bool(this->pred()(x,this->key_from(p[n]))))){
|
||||||
f(pg,n,p+n);
|
f(pg,n,p+n);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -1236,7 +1236,7 @@ private:
|
|||||||
do{
|
do{
|
||||||
auto n=unchecked_countr_zero(mask);
|
auto n=unchecked_countr_zero(mask);
|
||||||
if(BOOST_LIKELY(
|
if(BOOST_LIKELY(
|
||||||
pg->is_occupied(n)&&
|
is_occupied(pg,n)&&
|
||||||
bool(this->pred()(*it,this->key_from(p[n]))))){
|
bool(this->pred()(*it,this->key_from(p[n]))))){
|
||||||
f(cast_for(access_mode,type_policy::value_from(p[n])));
|
f(cast_for(access_mode,type_policy::value_from(p[n])));
|
||||||
++res;
|
++res;
|
||||||
@@ -1436,10 +1436,103 @@ private:
|
|||||||
bool commit_=false;
|
bool commit_=false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct latch_free_reserve_slot
|
||||||
|
{
|
||||||
|
latch_free_reserve_slot(group_type* pg_,std::size_t pos_):pg{pg_},pos{pos_}
|
||||||
|
{
|
||||||
|
unsigned char expected=0;
|
||||||
|
succeeded_=reinterpret_cast<std::atomic<unsigned char>*>(pg)[pos].
|
||||||
|
compare_exchange_weak(expected,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
~latch_free_reserve_slot()
|
||||||
|
{
|
||||||
|
if(succeeded_&&!commit_)pg->reset(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool succeeded()const{return succeeded_;}
|
||||||
|
|
||||||
|
void commit(){commit_=true;}
|
||||||
|
|
||||||
|
group_type *pg;
|
||||||
|
std::size_t pos;
|
||||||
|
bool succeeded_;
|
||||||
|
bool commit_=false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct assign_insert_counter_on_exit
|
||||||
|
{
|
||||||
|
~assign_insert_counter_on_exit(){counter=x;}
|
||||||
|
|
||||||
|
group_insert_counter_type &counter;
|
||||||
|
boost::uint32_t x;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename GroupAccessMode,typename F,typename... Args>
|
template<typename GroupAccessMode,typename F,typename... Args>
|
||||||
BOOST_FORCEINLINE int
|
BOOST_FORCEINLINE int
|
||||||
unprotected_norehash_emplace_or_visit(
|
unprotected_norehash_emplace_or_visit(
|
||||||
GroupAccessMode access_mode,F&& f,Args&&... args)
|
GroupAccessMode access_mode,F&& f,Args&&... args)
|
||||||
|
{
|
||||||
|
return unprotected_norehash_emplace_or_visit_with_layout(
|
||||||
|
std::integral_constant<bool,group_type::regular_layout>{},
|
||||||
|
access_mode,std::forward<F>(f),std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename GroupAccessMode,typename F,typename... Args>
|
||||||
|
BOOST_FORCEINLINE int
|
||||||
|
unprotected_norehash_emplace_or_visit_with_layout(
|
||||||
|
std::true_type, /* regular layout, almost-latch-free */
|
||||||
|
GroupAccessMode access_mode,F&& f,Args&&... args)
|
||||||
|
{
|
||||||
|
const auto &k=this->key_from(std::forward<Args>(args)...);
|
||||||
|
auto hash=this->hash_for(k);
|
||||||
|
auto pos0=this->position_for(hash);
|
||||||
|
|
||||||
|
for(;;){
|
||||||
|
startover:
|
||||||
|
boost::uint32_t counter=0;
|
||||||
|
while(BOOST_UNLIKELY((counter=insert_counter(pos0))%2==1)){}
|
||||||
|
if(unprotected_visit(
|
||||||
|
access_mode,k,pos0,hash,std::forward<F>(f)))return 0;
|
||||||
|
|
||||||
|
reserve_size rsize(*this);
|
||||||
|
if(BOOST_LIKELY(rsize.succeeded())){
|
||||||
|
for(prober pb(pos0);;pb.next(this->arrays.groups_size_mask)){
|
||||||
|
auto pos=pb.get();
|
||||||
|
auto pg=this->arrays.groups()+pos;
|
||||||
|
auto mask=pg->match_available();
|
||||||
|
if(BOOST_LIKELY(mask!=0)){
|
||||||
|
auto n=unchecked_countr_zero(mask);
|
||||||
|
latch_free_reserve_slot rslot{pg,n};
|
||||||
|
if(BOOST_UNLIKELY(!rslot.succeeded())){
|
||||||
|
/* slot wasn't empty */
|
||||||
|
goto startover;
|
||||||
|
}
|
||||||
|
if(BOOST_UNLIKELY(
|
||||||
|
!insert_counter(pos0).compare_exchange_weak(counter,counter+1))){
|
||||||
|
/* other thread inserted from pos0, need to start over */
|
||||||
|
goto startover;
|
||||||
|
}
|
||||||
|
assign_insert_counter_on_exit a{insert_counter(pos0),counter+2};
|
||||||
|
auto p=this->arrays.elements()+pos*N+n;
|
||||||
|
this->construct_element(p,std::forward<Args>(args)...);
|
||||||
|
pg->set(n,hash);
|
||||||
|
rslot.commit();
|
||||||
|
rsize.commit();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
pg->mark_overflow(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename GroupAccessMode,typename F,typename... Args>
|
||||||
|
BOOST_FORCEINLINE int
|
||||||
|
unprotected_norehash_emplace_or_visit_with_layout(
|
||||||
|
std::false_type, /* non-regular layout, latched */
|
||||||
|
GroupAccessMode access_mode,F&& f,Args&&... args)
|
||||||
{
|
{
|
||||||
const auto &k=this->key_from(std::forward<Args>(args)...);
|
const auto &k=this->key_from(std::forward<Args>(args)...);
|
||||||
auto hash=this->hash_for(k);
|
auto hash=this->hash_for(k);
|
||||||
@@ -1486,6 +1579,46 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check occupation with previous unsynced match */
|
||||||
|
|
||||||
|
static bool is_occupied(group_type* pg,std::size_t pos)
|
||||||
|
{
|
||||||
|
return is_occupied(
|
||||||
|
std::integral_constant<bool,group_type::regular_layout>{},pg,pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_occupied(std::true_type,group_type* pg,std::size_t pos)
|
||||||
|
{
|
||||||
|
/* regular layout, almost-latch-free insertion -> possible reserved slot */
|
||||||
|
return reinterpret_cast<std::atomic<unsigned char>*>(pg)[pos]>1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_occupied(std::false_type,group_type* pg,std::size_t pos)
|
||||||
|
{
|
||||||
|
/* non-regular layout, latched insertion -> no reserved slots */
|
||||||
|
return pg->is_occupied(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check occupation with previous synced match */
|
||||||
|
|
||||||
|
static bool is_really_occupied(group_type* pg,std::size_t pos)
|
||||||
|
{
|
||||||
|
return is_really_occupied(
|
||||||
|
std::integral_constant<bool,group_type::regular_layout>{},pg,pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_really_occupied(std::true_type,group_type* pg,std::size_t pos)
|
||||||
|
{
|
||||||
|
/* regular layout, almost-latch-free insertion -> possible reserved slot */
|
||||||
|
return reinterpret_cast<std::atomic<unsigned char>*>(pg)[pos]>1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_really_occupied(std::false_type,group_type*,std::size_t)
|
||||||
|
{
|
||||||
|
/* non-regular layout, latched insertion -> no false positives */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename GroupAccessMode,typename F>
|
template<typename GroupAccessMode,typename F>
|
||||||
auto for_all_elements(GroupAccessMode access_mode,F f)const
|
auto for_all_elements(GroupAccessMode access_mode,F f)const
|
||||||
->decltype(f(nullptr),void())
|
->decltype(f(nullptr),void())
|
||||||
@@ -1523,7 +1656,7 @@ private:
|
|||||||
auto mask=this->match_really_occupied(pg,last);
|
auto mask=this->match_really_occupied(pg,last);
|
||||||
while(mask){
|
while(mask){
|
||||||
auto n=unchecked_countr_zero(mask);
|
auto n=unchecked_countr_zero(mask);
|
||||||
if(!f(pg,n,p+n))return false;
|
if(BOOST_LIKELY(is_really_occupied(pg,n))&&!f(pg,n,p+n))return false;
|
||||||
mask&=mask-1;
|
mask&=mask-1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1558,7 +1691,7 @@ private:
|
|||||||
auto mask=this->match_really_occupied(&g,last);
|
auto mask=this->match_really_occupied(&g,last);
|
||||||
while(mask){
|
while(mask){
|
||||||
auto n=unchecked_countr_zero(mask);
|
auto n=unchecked_countr_zero(mask);
|
||||||
f(&g,n,p+n);
|
if(BOOST_LIKELY(is_really_occupied(&g,n)))f(&g,n,p+n);
|
||||||
mask&=mask-1;
|
mask&=mask-1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1580,7 +1713,7 @@ private:
|
|||||||
auto mask=this->match_really_occupied(&g,last);
|
auto mask=this->match_really_occupied(&g,last);
|
||||||
while(mask){
|
while(mask){
|
||||||
auto n=unchecked_countr_zero(mask);
|
auto n=unchecked_countr_zero(mask);
|
||||||
if(!f(p+n))return false;
|
if(BOOST_LIKELY(is_really_occupied(&g,n))&&!f(p+n))return false;
|
||||||
mask&=mask-1;
|
mask&=mask-1;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// Copyright (C) 2023 Braden Ganetsky
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
#ifndef BOOST_UNORDERED_DETAIL_THROW_EXCEPTION_HPP
|
||||||
|
#define BOOST_UNORDERED_DETAIL_THROW_EXCEPTION_HPP
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/throw_exception.hpp>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace unordered {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
BOOST_NOINLINE BOOST_NORETURN inline void throw_out_of_range(
|
||||||
|
char const* message)
|
||||||
|
{
|
||||||
|
boost::throw_exception(std::out_of_range(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace unordered
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif // BOOST_UNORDERED_DETAIL_THROW_EXCEPTION_HPP
|
||||||
@@ -14,12 +14,12 @@
|
|||||||
#include <boost/unordered/detail/foa/flat_map_types.hpp>
|
#include <boost/unordered/detail/foa/flat_map_types.hpp>
|
||||||
#include <boost/unordered/detail/foa/table.hpp>
|
#include <boost/unordered/detail/foa/table.hpp>
|
||||||
#include <boost/unordered/detail/serialize_container.hpp>
|
#include <boost/unordered/detail/serialize_container.hpp>
|
||||||
|
#include <boost/unordered/detail/throw_exception.hpp>
|
||||||
#include <boost/unordered/detail/type_traits.hpp>
|
#include <boost/unordered/detail/type_traits.hpp>
|
||||||
#include <boost/unordered/unordered_flat_map_fwd.hpp>
|
#include <boost/unordered/unordered_flat_map_fwd.hpp>
|
||||||
|
|
||||||
#include <boost/core/allocator_access.hpp>
|
#include <boost/core/allocator_access.hpp>
|
||||||
#include <boost/container_hash/hash.hpp>
|
#include <boost/container_hash/hash.hpp>
|
||||||
#include <boost/throw_exception.hpp>
|
|
||||||
|
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
@@ -459,8 +459,8 @@ namespace boost {
|
|||||||
// TODO: someday refactor this to conditionally serialize the key and
|
// TODO: someday refactor this to conditionally serialize the key and
|
||||||
// include it in the error message
|
// include it in the error message
|
||||||
//
|
//
|
||||||
boost::throw_exception(
|
boost::unordered::detail::throw_out_of_range(
|
||||||
std::out_of_range("key was not found in unordered_flat_map"));
|
"key was not found in unordered_flat_map");
|
||||||
}
|
}
|
||||||
|
|
||||||
mapped_type const& at(key_type const& key) const
|
mapped_type const& at(key_type const& key) const
|
||||||
@@ -469,8 +469,8 @@ namespace boost {
|
|||||||
if (pos != table_.end()) {
|
if (pos != table_.end()) {
|
||||||
return pos->second;
|
return pos->second;
|
||||||
}
|
}
|
||||||
boost::throw_exception(
|
boost::unordered::detail::throw_out_of_range(
|
||||||
std::out_of_range("key was not found in unordered_flat_map"));
|
"key was not found in unordered_flat_map");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class K>
|
template <class K>
|
||||||
@@ -483,8 +483,8 @@ namespace boost {
|
|||||||
if (pos != table_.end()) {
|
if (pos != table_.end()) {
|
||||||
return pos->second;
|
return pos->second;
|
||||||
}
|
}
|
||||||
boost::throw_exception(
|
boost::unordered::detail::throw_out_of_range(
|
||||||
std::out_of_range("key was not found in unordered_flat_map"));
|
"key was not found in unordered_flat_map");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class K>
|
template <class K>
|
||||||
@@ -497,8 +497,8 @@ namespace boost {
|
|||||||
if (pos != table_.end()) {
|
if (pos != table_.end()) {
|
||||||
return pos->second;
|
return pos->second;
|
||||||
}
|
}
|
||||||
boost::throw_exception(
|
boost::unordered::detail::throw_out_of_range(
|
||||||
std::out_of_range("key was not found in unordered_flat_map"));
|
"key was not found in unordered_flat_map");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FORCEINLINE mapped_type& operator[](key_type const& key)
|
BOOST_FORCEINLINE mapped_type& operator[](key_type const& key)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include <boost/unordered/detail/map.hpp>
|
#include <boost/unordered/detail/map.hpp>
|
||||||
#include <boost/unordered/detail/serialize_fca_container.hpp>
|
#include <boost/unordered/detail/serialize_fca_container.hpp>
|
||||||
|
#include <boost/unordered/detail/throw_exception.hpp>
|
||||||
#include <boost/unordered/detail/type_traits.hpp>
|
#include <boost/unordered/detail/type_traits.hpp>
|
||||||
|
|
||||||
#include <boost/container_hash/hash.hpp>
|
#include <boost/container_hash/hash.hpp>
|
||||||
@@ -1586,8 +1587,8 @@ namespace boost {
|
|||||||
return p->value().second;
|
return p->value().second;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::throw_exception(
|
boost::unordered::detail::throw_out_of_range(
|
||||||
std::out_of_range("Unable to find key in unordered_map."));
|
"Unable to find key in unordered_map.");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class K, class T, class H, class P, class A>
|
template <class K, class T, class H, class P, class A>
|
||||||
@@ -1602,8 +1603,8 @@ namespace boost {
|
|||||||
return p->value().second;
|
return p->value().second;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::throw_exception(
|
boost::unordered::detail::throw_out_of_range(
|
||||||
std::out_of_range("Unable to find key in unordered_map."));
|
"Unable to find key in unordered_map.");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class K, class T, class H, class P, class A>
|
template <class K, class T, class H, class P, class A>
|
||||||
@@ -1620,8 +1621,8 @@ namespace boost {
|
|||||||
return p->value().second;
|
return p->value().second;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::throw_exception(
|
boost::unordered::detail::throw_out_of_range(
|
||||||
std::out_of_range("Unable to find key in unordered_map."));
|
"Unable to find key in unordered_map.");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class K, class T, class H, class P, class A>
|
template <class K, class T, class H, class P, class A>
|
||||||
@@ -1638,8 +1639,8 @@ namespace boost {
|
|||||||
return p->value().second;
|
return p->value().second;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::throw_exception(
|
boost::unordered::detail::throw_out_of_range(
|
||||||
std::out_of_range("Unable to find key in unordered_map."));
|
"Unable to find key in unordered_map.");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class K, class T, class H, class P, class A>
|
template <class K, class T, class H, class P, class A>
|
||||||
|
|||||||
@@ -15,12 +15,12 @@
|
|||||||
#include <boost/unordered/detail/foa/node_map_types.hpp>
|
#include <boost/unordered/detail/foa/node_map_types.hpp>
|
||||||
#include <boost/unordered/detail/foa/table.hpp>
|
#include <boost/unordered/detail/foa/table.hpp>
|
||||||
#include <boost/unordered/detail/serialize_container.hpp>
|
#include <boost/unordered/detail/serialize_container.hpp>
|
||||||
|
#include <boost/unordered/detail/throw_exception.hpp>
|
||||||
#include <boost/unordered/detail/type_traits.hpp>
|
#include <boost/unordered/detail/type_traits.hpp>
|
||||||
#include <boost/unordered/unordered_node_map_fwd.hpp>
|
#include <boost/unordered/unordered_node_map_fwd.hpp>
|
||||||
|
|
||||||
#include <boost/core/allocator_access.hpp>
|
#include <boost/core/allocator_access.hpp>
|
||||||
#include <boost/container_hash/hash.hpp>
|
#include <boost/container_hash/hash.hpp>
|
||||||
#include <boost/throw_exception.hpp>
|
|
||||||
|
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
@@ -554,8 +554,8 @@ namespace boost {
|
|||||||
// TODO: someday refactor this to conditionally serialize the key and
|
// TODO: someday refactor this to conditionally serialize the key and
|
||||||
// include it in the error message
|
// include it in the error message
|
||||||
//
|
//
|
||||||
boost::throw_exception(
|
boost::unordered::detail::throw_out_of_range(
|
||||||
std::out_of_range("key was not found in unordered_node_map"));
|
"key was not found in unordered_node_map");
|
||||||
}
|
}
|
||||||
|
|
||||||
mapped_type const& at(key_type const& key) const
|
mapped_type const& at(key_type const& key) const
|
||||||
@@ -564,8 +564,8 @@ namespace boost {
|
|||||||
if (pos != table_.end()) {
|
if (pos != table_.end()) {
|
||||||
return pos->second;
|
return pos->second;
|
||||||
}
|
}
|
||||||
boost::throw_exception(
|
boost::unordered::detail::throw_out_of_range(
|
||||||
std::out_of_range("key was not found in unordered_node_map"));
|
"key was not found in unordered_node_map");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class K>
|
template <class K>
|
||||||
@@ -578,8 +578,8 @@ namespace boost {
|
|||||||
if (pos != table_.end()) {
|
if (pos != table_.end()) {
|
||||||
return pos->second;
|
return pos->second;
|
||||||
}
|
}
|
||||||
boost::throw_exception(
|
boost::unordered::detail::throw_out_of_range(
|
||||||
std::out_of_range("key was not found in unordered_node_map"));
|
"key was not found in unordered_node_map");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class K>
|
template <class K>
|
||||||
@@ -592,8 +592,8 @@ namespace boost {
|
|||||||
if (pos != table_.end()) {
|
if (pos != table_.end()) {
|
||||||
return pos->second;
|
return pos->second;
|
||||||
}
|
}
|
||||||
boost::throw_exception(
|
boost::unordered::detail::throw_out_of_range(
|
||||||
std::out_of_range("key was not found in unordered_node_map"));
|
"key was not found in unordered_node_map");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FORCEINLINE mapped_type& operator[](key_type const& key)
|
BOOST_FORCEINLINE mapped_type& operator[](key_type const& key)
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@ if(HAVE_BOOST_TEST)
|
|||||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
set(BOOST_TEST_LINK_LIBRARIES Boost::unordered Boost::core Boost::concept_check)
|
set(BOOST_TEST_LINK_LIBRARIES Boost::unordered Boost::core Boost::concept_check Boost::tuple)
|
||||||
|
|
||||||
function(fca_tests)
|
function(fca_tests)
|
||||||
boost_test(PREFIX boost_unordered ${ARGN})
|
boost_test(PREFIX boost_unordered ${ARGN})
|
||||||
|
|||||||
Reference in New Issue
Block a user