mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-31 11:57:15 +02:00
Unordered: Use std::allocator_trait's variadic construct.
[SVN r78349]
This commit is contained in:
@ -15,14 +15,7 @@
|
|||||||
# pragma once
|
# pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <boost/config.hpp>
|
#include <boost/unordered/detail/emplace_args.hpp>
|
||||||
#include <boost/detail/select_type.hpp>
|
|
||||||
#include <boost/utility/enable_if.hpp>
|
|
||||||
#include <boost/preprocessor/cat.hpp>
|
|
||||||
#include <boost/preprocessor/enum.hpp>
|
|
||||||
#include <boost/limits.hpp>
|
|
||||||
#include <boost/type_traits/add_lvalue_reference.hpp>
|
|
||||||
#include <boost/pointer_to_other.hpp>
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/utility/addressof.hpp>
|
#include <boost/utility/addressof.hpp>
|
||||||
|
|
||||||
@ -31,23 +24,29 @@
|
|||||||
# if defined(__GXX_EXPERIMENTAL_CXX0X__) && \
|
# if defined(__GXX_EXPERIMENTAL_CXX0X__) && \
|
||||||
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
|
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
|
||||||
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1
|
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1
|
||||||
# elif BOOST_MSVC >= 1700 && defined(_CPPLIB_VER)
|
# elif defined(BOOST_MSVC)
|
||||||
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1
|
# if BOOST_MSVC < 1400
|
||||||
|
// Use container's allocator_traits for older versions of Visual
|
||||||
|
// C++ as I don't test with them.
|
||||||
|
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 2
|
||||||
|
# elif BOOST_MSVC >= 1700
|
||||||
|
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1
|
||||||
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
// Use container's allocator_traits for older versions of Visual C++ as I don't
|
|
||||||
// test with them.
|
|
||||||
# if defined(BOOST_MSVC) && BOOST_MSVC < 1400
|
|
||||||
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 2
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
|
#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
|
||||||
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
|
# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
|
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 0
|
||||||
|
# include <boost/limits.hpp>
|
||||||
|
# include <boost/utility/enable_if.hpp>
|
||||||
|
# include <boost/pointer_to_other.hpp>
|
||||||
|
# if defined(BOOST_NO_SFINAE_EXPR)
|
||||||
|
# include <boost/type_traits/is_same.hpp>
|
||||||
|
# endif
|
||||||
|
#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
|
||||||
# include <memory>
|
# include <memory>
|
||||||
#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
|
#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
|
||||||
# include <boost/container/allocator_traits.hpp>
|
# include <boost/container/allocator_traits.hpp>
|
||||||
@ -57,6 +56,7 @@
|
|||||||
# include <type_traits>
|
# include <type_traits>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace boost { namespace unordered { namespace detail {
|
namespace boost { namespace unordered { namespace detail {
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
@ -98,43 +98,10 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Bits and pieces for implementing traits
|
// Expression test mechanism
|
||||||
//
|
|
||||||
// Some of these are also used elsewhere
|
|
||||||
|
|
||||||
template <typename T> typename boost::add_lvalue_reference<T>::type make();
|
|
||||||
struct choice9 { typedef char (&type)[9]; };
|
|
||||||
struct choice8 : choice9 { typedef char (&type)[8]; };
|
|
||||||
struct choice7 : choice8 { typedef char (&type)[7]; };
|
|
||||||
struct choice6 : choice7 { typedef char (&type)[6]; };
|
|
||||||
struct choice5 : choice6 { typedef char (&type)[5]; };
|
|
||||||
struct choice4 : choice5 { typedef char (&type)[4]; };
|
|
||||||
struct choice3 : choice4 { typedef char (&type)[3]; };
|
|
||||||
struct choice2 : choice3 { typedef char (&type)[2]; };
|
|
||||||
struct choice1 : choice2 { typedef char (&type)[1]; };
|
|
||||||
choice1 choose();
|
|
||||||
|
|
||||||
typedef choice1::type yes_type;
|
|
||||||
typedef choice2::type no_type;
|
|
||||||
|
|
||||||
struct private_type
|
|
||||||
{
|
|
||||||
private_type const &operator,(int) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
no_type is_private_type(T const&);
|
|
||||||
yes_type is_private_type(private_type const&);
|
|
||||||
|
|
||||||
struct convert_from_anything {
|
|
||||||
template <typename T>
|
|
||||||
convert_from_anything(T const&);
|
|
||||||
};
|
|
||||||
|
|
||||||
#if !defined(BOOST_NO_SFINAE_EXPR)
|
#if !defined(BOOST_NO_SFINAE_EXPR)
|
||||||
|
|
||||||
# define BOOST_UNORDERED_HAVE_CALL_DETECTION 1
|
|
||||||
|
|
||||||
template <typename T, unsigned int> struct expr_test;
|
template <typename T, unsigned int> struct expr_test;
|
||||||
template <typename T> struct expr_test<T, sizeof(char)> : T {};
|
template <typename T> struct expr_test<T, sizeof(char)> : T {};
|
||||||
template <typename U> static char for_expr_test(U const&);
|
template <typename U> static char for_expr_test(U const&);
|
||||||
@ -165,8 +132,6 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
# define BOOST_UNORDERED_HAVE_CALL_DETECTION 0
|
|
||||||
|
|
||||||
template <typename T> struct identity { typedef T type; };
|
template <typename T> struct identity { typedef T type; };
|
||||||
|
|
||||||
#define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
|
#define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
|
||||||
@ -209,12 +174,11 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Allocator traits
|
// Allocator traits
|
||||||
//
|
|
||||||
// Uses the standard versions if available.
|
|
||||||
// (although untested as I don't have access to a standard version yet)
|
|
||||||
|
|
||||||
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
|
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
|
||||||
|
|
||||||
|
#define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
|
||||||
|
|
||||||
template <typename Alloc>
|
template <typename Alloc>
|
||||||
struct allocator_traits : std::allocator_traits<Alloc> {};
|
struct allocator_traits : std::allocator_traits<Alloc> {};
|
||||||
|
|
||||||
@ -227,6 +191,8 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
|
|
||||||
#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
|
#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
|
||||||
|
|
||||||
|
#define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
|
||||||
|
|
||||||
template <typename Alloc>
|
template <typename Alloc>
|
||||||
struct allocator_traits :
|
struct allocator_traits :
|
||||||
boost::container::allocator_traits<Alloc> {};
|
boost::container::allocator_traits<Alloc> {};
|
||||||
@ -239,6 +205,13 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||||
|
# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
|
||||||
|
#else
|
||||||
|
# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// TODO: Does this match std::allocator_traits<Alloc>::rebind_alloc<T>?
|
// TODO: Does this match std::allocator_traits<Alloc>::rebind_alloc<T>?
|
||||||
template <typename Alloc, typename T>
|
template <typename Alloc, typename T>
|
||||||
struct rebind_wrap
|
struct rebind_wrap
|
||||||
@ -309,7 +282,7 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
|
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
|
||||||
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
|
BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
|
||||||
|
|
||||||
#if BOOST_UNORDERED_HAVE_CALL_DETECTION
|
#if !defined(BOOST_NO_SFINAE_EXPR)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
BOOST_UNORDERED_HAS_FUNCTION(
|
BOOST_UNORDERED_HAS_FUNCTION(
|
||||||
select_on_container_copy_construction, U const, (), 0
|
select_on_container_copy_construction, U const, (), 0
|
||||||
@ -320,12 +293,21 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
max_size, U const, (), 0
|
max_size, U const, (), 0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
# if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||||
|
template <typename T, typename ValueType, typename... Args>
|
||||||
|
BOOST_UNORDERED_HAS_FUNCTION(
|
||||||
|
construct, U, (
|
||||||
|
boost::unordered::detail::make<ValueType*>(),
|
||||||
|
boost::unordered::detail::make<Args const>()...), 2
|
||||||
|
);
|
||||||
|
# else
|
||||||
template <typename T, typename ValueType>
|
template <typename T, typename ValueType>
|
||||||
BOOST_UNORDERED_HAS_FUNCTION(
|
BOOST_UNORDERED_HAS_FUNCTION(
|
||||||
construct, U, (
|
construct, U, (
|
||||||
boost::unordered::detail::make<ValueType*>(),
|
boost::unordered::detail::make<ValueType*>(),
|
||||||
boost::unordered::detail::make<ValueType const>()), 2
|
boost::unordered::detail::make<ValueType const>()), 2
|
||||||
);
|
);
|
||||||
|
# endif
|
||||||
|
|
||||||
template <typename T, typename ValueType>
|
template <typename T, typename ValueType>
|
||||||
BOOST_UNORDERED_HAS_FUNCTION(
|
BOOST_UNORDERED_HAS_FUNCTION(
|
||||||
@ -425,7 +407,27 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Only supporting the basic copy constructor for now.
|
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||||
|
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
static typename boost::enable_if_c<
|
||||||
|
boost::unordered::detail::has_construct<Alloc, T, Args...>
|
||||||
|
::value>::type
|
||||||
|
construct(Alloc& a, T* p, Args&&... x)
|
||||||
|
{
|
||||||
|
a.construct(p, boost::forward<Args>(x)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
static typename boost::disable_if_c<
|
||||||
|
boost::unordered::detail::has_construct<Alloc, T, Args...>
|
||||||
|
::value>::type
|
||||||
|
construct(Alloc&, T* p, Args&&... x)
|
||||||
|
{
|
||||||
|
new ((void*) p) T(boost::forward<Args>(x)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif !defined(BOOST_NO_SFINAE_EXPR)
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static typename boost::enable_if_c<
|
static typename boost::enable_if_c<
|
||||||
@ -443,6 +445,34 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
new ((void*) p) T(x);
|
new ((void*) p) T(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// If we don't have SFINAE expressions, only construct the type
|
||||||
|
// that matches the allocator.
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static typename boost::enable_if_c<
|
||||||
|
boost::unordered::detail::has_construct<Alloc, T>::value &&
|
||||||
|
boost::is_same<T, value_type>::value
|
||||||
|
>::type
|
||||||
|
construct(Alloc& a, T* p, T const& x)
|
||||||
|
{
|
||||||
|
a.construct(p, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static typename boost::disable_if_c<
|
||||||
|
boost::unordered::detail::has_construct<Alloc, T>::value &&
|
||||||
|
boost::is_same<T, value_type>::value
|
||||||
|
>::type
|
||||||
|
construct(Alloc&, T* p, T const& x)
|
||||||
|
{
|
||||||
|
new ((void*) p) T(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static typename boost::enable_if_c<
|
static typename boost::enable_if_c<
|
||||||
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
|
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
|
||||||
@ -459,6 +489,48 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
boost::unordered::detail::destroy(p);
|
boost::unordered::detail::destroy(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif !defined(BOOST_NO_SFINAE_EXPR)
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static typename boost::enable_if_c<
|
||||||
|
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
|
||||||
|
destroy(Alloc& a, T* p)
|
||||||
|
{
|
||||||
|
a.destroy(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static typename boost::disable_if_c<
|
||||||
|
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
|
||||||
|
destroy(Alloc&, T* p)
|
||||||
|
{
|
||||||
|
boost::unordered::detail::destroy(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static typename boost::enable_if_c<
|
||||||
|
boost::unordered::detail::has_destroy<Alloc, T>::value &&
|
||||||
|
boost::is_same<T, value_type>::value
|
||||||
|
>::type
|
||||||
|
destroy(Alloc& a, T* p)
|
||||||
|
{
|
||||||
|
a.destroy(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static typename boost::disable_if_c<
|
||||||
|
boost::unordered::detail::has_destroy<Alloc, T>::value &&
|
||||||
|
boost::is_same<T, value_type>::value
|
||||||
|
>::type
|
||||||
|
destroy(Alloc&, T* p)
|
||||||
|
{
|
||||||
|
boost::unordered::detail::destroy(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static size_type max_size(const Alloc& a)
|
static size_type max_size(const Alloc& a)
|
||||||
{
|
{
|
||||||
return boost::unordered::detail::call_max_size<size_type>(a);
|
return boost::unordered::detail::call_max_size<size_type>(a);
|
||||||
@ -488,6 +560,41 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
#undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
|
#undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
|
||||||
#undef BOOST_UNORDERED_DEFAULT_TYPE
|
#undef BOOST_UNORDERED_DEFAULT_TYPE
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
|
||||||
|
template <typename Alloc, typename T, BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||||
|
inline void construct_node(Alloc& a, T* p, BOOST_UNORDERED_EMPLACE_ARGS)
|
||||||
|
{
|
||||||
|
boost::unordered::detail::allocator_traits<Alloc>::construct(
|
||||||
|
a, p, BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Alloc, typename T>
|
||||||
|
inline void destroy_node(Alloc& a, T* p)
|
||||||
|
{
|
||||||
|
boost::unordered::detail::allocator_traits<Alloc>::destroy(a, p);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
template <typename Alloc, typename T, BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||||
|
inline void construct_node(Alloc& a, T* p, BOOST_UNORDERED_EMPLACE_ARGS)
|
||||||
|
{
|
||||||
|
boost::unordered::detail::allocator_traits<Alloc>::construct(a, p, T());
|
||||||
|
try {
|
||||||
|
boost::unordered::detail::construct_impl(
|
||||||
|
p->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||||
|
} catch(...) {
|
||||||
|
boost::unordered::detail::allocator_traits<Alloc>::destroy(a, p);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Alloc, typename T>
|
||||||
|
inline void destroy_node(Alloc& a, T* p)
|
||||||
|
{
|
||||||
|
boost::unordered::detail::destroy(p->value_ptr());
|
||||||
|
boost::unordered::detail::allocator_traits<Alloc>::destroy(a, p);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// array_constructor
|
// array_constructor
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
#include <boost/unordered/detail/util.hpp>
|
#include <boost/unordered/detail/util.hpp>
|
||||||
#include <boost/unordered/detail/allocator_helpers.hpp>
|
#include <boost/unordered/detail/allocator_helpers.hpp>
|
||||||
#include <boost/unordered/detail/emplace_args.hpp>
|
|
||||||
#include <boost/type_traits/aligned_storage.hpp>
|
#include <boost/type_traits/aligned_storage.hpp>
|
||||||
#include <boost/type_traits/alignment_of.hpp>
|
#include <boost/type_traits/alignment_of.hpp>
|
||||||
#include <boost/swap.hpp>
|
#include <boost/swap.hpp>
|
||||||
@ -54,16 +53,14 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
|
|
||||||
node_allocator& alloc_;
|
node_allocator& alloc_;
|
||||||
node_pointer node_;
|
node_pointer node_;
|
||||||
bool node_constructed_;
|
bool constructed_;
|
||||||
bool value_constructed_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
node_constructor(node_allocator& n) :
|
node_constructor(node_allocator& n) :
|
||||||
alloc_(n),
|
alloc_(n),
|
||||||
node_(),
|
node_(),
|
||||||
node_constructed_(false),
|
constructed_(false)
|
||||||
value_constructed_(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,26 +71,40 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||||
void construct_value(BOOST_UNORDERED_EMPLACE_ARGS)
|
void construct_value(BOOST_UNORDERED_EMPLACE_ARGS)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(node_ && node_constructed_ && !value_constructed_);
|
BOOST_ASSERT(node_ && !constructed_);
|
||||||
boost::unordered::detail::construct_impl(
|
boost::unordered::detail::construct_node(alloc_,
|
||||||
node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
|
boost::addressof(*node_), BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||||
value_constructed_ = true;
|
node_->init(static_cast<typename node::link_pointer>(node_));
|
||||||
|
constructed_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename A0>
|
template <typename A0>
|
||||||
void construct_value2(BOOST_FWD_REF(A0) a0)
|
void construct_value2(BOOST_FWD_REF(A0) a0)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(node_ && node_constructed_ && !value_constructed_);
|
BOOST_ASSERT(node_ && !constructed_);
|
||||||
boost::unordered::detail::construct_impl2(
|
# if defined(BOOST_UNORDERED_VARIADIC_MOVE)
|
||||||
node_->value_ptr(), boost::forward<A0>(a0));
|
boost::unordered::detail::construct_node(alloc_,
|
||||||
value_constructed_ = true;
|
boost::addressof(*node_), boost::forward<A0>(a0));
|
||||||
|
# else
|
||||||
|
boost::unordered::detail::construct_node(alloc_,
|
||||||
|
boost::addressof(*node_),
|
||||||
|
boost::unordered::detail::create_emplace_args(
|
||||||
|
boost::forward<A0>(a0)));
|
||||||
|
# endif
|
||||||
|
constructed_ = true;
|
||||||
|
node_->init(static_cast<typename node::link_pointer>(node_));
|
||||||
}
|
}
|
||||||
|
|
||||||
value_type const& value() const {
|
value_type const& value() const {
|
||||||
BOOST_ASSERT(node_ && node_constructed_ && value_constructed_);
|
BOOST_ASSERT(node_ && constructed_);
|
||||||
return node_->value();
|
return node_->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node_pointer get()
|
||||||
|
{
|
||||||
|
return node_;
|
||||||
|
}
|
||||||
|
|
||||||
// no throw
|
// no throw
|
||||||
node_pointer release()
|
node_pointer release()
|
||||||
{
|
{
|
||||||
@ -111,12 +122,8 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
node_constructor<Alloc>::~node_constructor()
|
node_constructor<Alloc>::~node_constructor()
|
||||||
{
|
{
|
||||||
if (node_) {
|
if (node_) {
|
||||||
if (value_constructed_) {
|
if (constructed_) {
|
||||||
boost::unordered::detail::destroy(node_->value_ptr());
|
boost::unordered::detail::destroy_node(alloc_,
|
||||||
}
|
|
||||||
|
|
||||||
if (node_constructed_) {
|
|
||||||
node_allocator_traits::destroy(alloc_,
|
|
||||||
boost::addressof(*node_));
|
boost::addressof(*node_));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,24 +135,13 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
void node_constructor<Alloc>::construct_node()
|
void node_constructor<Alloc>::construct_node()
|
||||||
{
|
{
|
||||||
if(!node_) {
|
if(!node_) {
|
||||||
node_constructed_ = false;
|
constructed_ = false;
|
||||||
value_constructed_ = false;
|
|
||||||
|
|
||||||
node_ = node_allocator_traits::allocate(alloc_, 1);
|
node_ = node_allocator_traits::allocate(alloc_, 1);
|
||||||
|
|
||||||
node_allocator_traits::construct(alloc_,
|
|
||||||
boost::addressof(*node_), node());
|
|
||||||
node_->init(static_cast<typename node::link_pointer>(node_));
|
|
||||||
node_constructed_ = true;
|
|
||||||
}
|
}
|
||||||
else {
|
else if (constructed_) {
|
||||||
BOOST_ASSERT(node_constructed_);
|
boost::unordered::detail::destroy_node(alloc_,
|
||||||
|
boost::addressof(*node_));
|
||||||
if (value_constructed_)
|
constructed_ = false;
|
||||||
{
|
|
||||||
boost::unordered::detail::destroy(node_->value_ptr());
|
|
||||||
value_constructed_ = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,6 +179,16 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
|
|
||||||
enum { extra_node = false };
|
enum { extra_node = false };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename LinkPointer>
|
||||||
|
struct node_base
|
||||||
|
{
|
||||||
|
typedef LinkPointer link_pointer;
|
||||||
|
link_pointer next_;
|
||||||
|
|
||||||
|
node_base() : next_() {}
|
||||||
|
};
|
||||||
|
|
||||||
}}}
|
}}}
|
||||||
|
|
||||||
namespace boost { namespace unordered { namespace iterator_detail {
|
namespace boost { namespace unordered { namespace iterator_detail {
|
||||||
@ -718,6 +724,14 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
node_constructor a(this->node_alloc());
|
node_constructor a(this->node_alloc());
|
||||||
a.construct_node();
|
a.construct_node();
|
||||||
|
|
||||||
|
// Since this node is just to mark the beginning it doesn't
|
||||||
|
// contain a value, so just construct node::node_base
|
||||||
|
// which containers the pointer to the next element.
|
||||||
|
node_allocator_traits::construct(node_alloc(),
|
||||||
|
static_cast<typename node::node_base*>(
|
||||||
|
boost::addressof(*a.get())),
|
||||||
|
typename node::node_base());
|
||||||
|
|
||||||
(constructor.get() +
|
(constructor.get() +
|
||||||
static_cast<std::ptrdiff_t>(this->bucket_count_))->next_ =
|
static_cast<std::ptrdiff_t>(this->bucket_count_))->next_ =
|
||||||
a.release();
|
a.release();
|
||||||
@ -762,9 +776,8 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
|
|
||||||
inline void delete_node(c_iterator n)
|
inline void delete_node(c_iterator n)
|
||||||
{
|
{
|
||||||
boost::unordered::detail::destroy(n.node_->value_ptr());
|
boost::unordered::detail::destroy_node(
|
||||||
node_allocator_traits::destroy(node_alloc(),
|
node_alloc(), boost::addressof(*n.node_));
|
||||||
boost::addressof(*n.node_));
|
|
||||||
node_allocator_traits::deallocate(node_alloc(), n.node_, 1);
|
node_allocator_traits::deallocate(node_alloc(), n.node_, 1);
|
||||||
--size_;
|
--size_;
|
||||||
}
|
}
|
||||||
@ -786,7 +799,8 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
inline void delete_extra_node(bucket_pointer) {}
|
inline void delete_extra_node(bucket_pointer) {}
|
||||||
|
|
||||||
inline void delete_extra_node(node_pointer n) {
|
inline void delete_extra_node(node_pointer n) {
|
||||||
node_allocator_traits::destroy(node_alloc(), boost::addressof(*n));
|
node_allocator_traits::destroy(node_alloc(),
|
||||||
|
static_cast<typename node::node_base*>(boost::addressof(*n)));
|
||||||
node_allocator_traits::deallocate(node_alloc(), n, 1);
|
node_allocator_traits::deallocate(node_alloc(), n, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
# pragma once
|
# pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <boost/unordered/detail/fwd.hpp>
|
||||||
#include <boost/move/move.hpp>
|
#include <boost/move/move.hpp>
|
||||||
#include <boost/preprocessor/cat.hpp>
|
#include <boost/preprocessor/cat.hpp>
|
||||||
#include <boost/preprocessor/inc.hpp>
|
#include <boost/preprocessor/inc.hpp>
|
||||||
@ -21,7 +22,10 @@
|
|||||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||||
#include <boost/type_traits/is_class.hpp>
|
#include <boost/type_traits/is_class.hpp>
|
||||||
|
#include <boost/type_traits/add_lvalue_reference.hpp>
|
||||||
#include <boost/tuple/tuple.hpp>
|
#include <boost/tuple/tuple.hpp>
|
||||||
|
#include <boost/utility/enable_if.hpp>
|
||||||
|
#include <boost/detail/select_type.hpp>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#if !defined(BOOST_NO_0X_HDR_TUPLE)
|
#if !defined(BOOST_NO_0X_HDR_TUPLE)
|
||||||
@ -45,6 +49,38 @@
|
|||||||
|
|
||||||
namespace boost { namespace unordered { namespace detail {
|
namespace boost { namespace unordered { namespace detail {
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Bits and pieces for implementing traits
|
||||||
|
|
||||||
|
template <typename T> typename boost::add_lvalue_reference<T>::type make();
|
||||||
|
struct choice9 { typedef char (&type)[9]; };
|
||||||
|
struct choice8 : choice9 { typedef char (&type)[8]; };
|
||||||
|
struct choice7 : choice8 { typedef char (&type)[7]; };
|
||||||
|
struct choice6 : choice7 { typedef char (&type)[6]; };
|
||||||
|
struct choice5 : choice6 { typedef char (&type)[5]; };
|
||||||
|
struct choice4 : choice5 { typedef char (&type)[4]; };
|
||||||
|
struct choice3 : choice4 { typedef char (&type)[3]; };
|
||||||
|
struct choice2 : choice3 { typedef char (&type)[2]; };
|
||||||
|
struct choice1 : choice2 { typedef char (&type)[1]; };
|
||||||
|
choice1 choose();
|
||||||
|
|
||||||
|
typedef choice1::type yes_type;
|
||||||
|
typedef choice2::type no_type;
|
||||||
|
|
||||||
|
struct private_type
|
||||||
|
{
|
||||||
|
private_type const &operator,(int) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
no_type is_private_type(T const&);
|
||||||
|
yes_type is_private_type(private_type const&);
|
||||||
|
|
||||||
|
struct convert_from_anything {
|
||||||
|
template <typename T>
|
||||||
|
convert_from_anything(T const&);
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// emplace_args
|
// emplace_args
|
||||||
//
|
//
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <boost/unordered/detail/table.hpp>
|
#include <boost/unordered/detail/table.hpp>
|
||||||
#include <boost/unordered/detail/emplace_args.hpp>
|
|
||||||
#include <boost/unordered/detail/extract_key.hpp>
|
#include <boost/unordered/detail/extract_key.hpp>
|
||||||
|
|
||||||
namespace boost { namespace unordered { namespace detail {
|
namespace boost { namespace unordered { namespace detail {
|
||||||
@ -23,20 +22,40 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
|
|
||||||
template <typename A, typename T>
|
template <typename A, typename T>
|
||||||
struct grouped_node :
|
struct grouped_node :
|
||||||
|
boost::unordered::detail::node_base<
|
||||||
|
typename ::boost::unordered::detail::rebind_wrap<
|
||||||
|
A, grouped_node<A, T> >::type::pointer
|
||||||
|
>,
|
||||||
boost::unordered::detail::value_base<T>
|
boost::unordered::detail::value_base<T>
|
||||||
{
|
{
|
||||||
typedef typename ::boost::unordered::detail::rebind_wrap<
|
typedef typename ::boost::unordered::detail::rebind_wrap<
|
||||||
A, grouped_node<A, T> >::type::pointer link_pointer;
|
A, grouped_node<A, T> >::type::pointer link_pointer;
|
||||||
|
typedef boost::unordered::detail::node_base<link_pointer> node_base;
|
||||||
|
|
||||||
link_pointer next_;
|
|
||||||
link_pointer group_prev_;
|
link_pointer group_prev_;
|
||||||
std::size_t hash_;
|
std::size_t hash_;
|
||||||
|
|
||||||
|
#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
|
||||||
|
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||||
|
grouped_node(BOOST_UNORDERED_EMPLACE_ARGS) :
|
||||||
|
node_base(),
|
||||||
|
group_prev_(),
|
||||||
|
hash_(0)
|
||||||
|
{
|
||||||
|
boost::unordered::detail::construct_impl(
|
||||||
|
this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
~grouped_node() {
|
||||||
|
boost::unordered::detail::destroy(this->value_ptr());
|
||||||
|
}
|
||||||
|
#else
|
||||||
grouped_node() :
|
grouped_node() :
|
||||||
next_(),
|
node_base(),
|
||||||
group_prev_(),
|
group_prev_(),
|
||||||
hash_(0)
|
hash_(0)
|
||||||
{}
|
{}
|
||||||
|
#endif
|
||||||
|
|
||||||
void init(link_pointer self)
|
void init(link_pointer self)
|
||||||
{
|
{
|
||||||
@ -50,16 +69,33 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
boost::unordered::detail::ptr_bucket
|
boost::unordered::detail::ptr_bucket
|
||||||
{
|
{
|
||||||
typedef boost::unordered::detail::ptr_bucket bucket_base;
|
typedef boost::unordered::detail::ptr_bucket bucket_base;
|
||||||
|
typedef bucket_base node_base;
|
||||||
typedef ptr_bucket* link_pointer;
|
typedef ptr_bucket* link_pointer;
|
||||||
|
|
||||||
link_pointer group_prev_;
|
link_pointer group_prev_;
|
||||||
std::size_t hash_;
|
std::size_t hash_;
|
||||||
|
|
||||||
|
#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
|
||||||
|
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||||
|
grouped_ptr_node(BOOST_UNORDERED_EMPLACE_ARGS) :
|
||||||
|
bucket_base(),
|
||||||
|
group_prev_(0),
|
||||||
|
hash_(0)
|
||||||
|
{
|
||||||
|
boost::unordered::detail::construct_impl(
|
||||||
|
this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
~grouped_ptr_node() {
|
||||||
|
boost::unordered::detail::destroy(this->value_ptr());
|
||||||
|
}
|
||||||
|
#else
|
||||||
grouped_ptr_node() :
|
grouped_ptr_node() :
|
||||||
bucket_base(),
|
bucket_base(),
|
||||||
group_prev_(0),
|
group_prev_(0),
|
||||||
hash_(0)
|
hash_(0)
|
||||||
{}
|
{}
|
||||||
|
#endif
|
||||||
|
|
||||||
void init(link_pointer self)
|
void init(link_pointer self)
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <boost/unordered/detail/table.hpp>
|
#include <boost/unordered/detail/table.hpp>
|
||||||
#include <boost/unordered/detail/emplace_args.hpp>
|
|
||||||
#include <boost/unordered/detail/extract_key.hpp>
|
#include <boost/unordered/detail/extract_key.hpp>
|
||||||
#include <boost/throw_exception.hpp>
|
#include <boost/throw_exception.hpp>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@ -25,18 +24,37 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
|
|
||||||
template <typename A, typename T>
|
template <typename A, typename T>
|
||||||
struct node :
|
struct node :
|
||||||
|
boost::unordered::detail::node_base<
|
||||||
|
typename ::boost::unordered::detail::rebind_wrap<
|
||||||
|
A, node<A, T> >::type::pointer
|
||||||
|
>,
|
||||||
boost::unordered::detail::value_base<T>
|
boost::unordered::detail::value_base<T>
|
||||||
{
|
{
|
||||||
typedef typename ::boost::unordered::detail::rebind_wrap<
|
typedef typename ::boost::unordered::detail::rebind_wrap<
|
||||||
A, node<A, T> >::type::pointer link_pointer;
|
A, node<A, T> >::type::pointer link_pointer;
|
||||||
|
typedef boost::unordered::detail::node_base<link_pointer> node_base;
|
||||||
|
|
||||||
link_pointer next_;
|
|
||||||
std::size_t hash_;
|
std::size_t hash_;
|
||||||
|
|
||||||
|
#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
|
||||||
|
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||||
|
node(BOOST_UNORDERED_EMPLACE_ARGS) :
|
||||||
|
node_base(),
|
||||||
|
hash_(0)
|
||||||
|
{
|
||||||
|
boost::unordered::detail::construct_impl(
|
||||||
|
this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
~node() {
|
||||||
|
boost::unordered::detail::destroy(this->value_ptr());
|
||||||
|
}
|
||||||
|
#else
|
||||||
node() :
|
node() :
|
||||||
next_(),
|
node_base(),
|
||||||
hash_(0)
|
hash_(0)
|
||||||
{}
|
{}
|
||||||
|
#endif
|
||||||
|
|
||||||
void init(link_pointer)
|
void init(link_pointer)
|
||||||
{
|
{
|
||||||
@ -49,14 +67,30 @@ namespace boost { namespace unordered { namespace detail {
|
|||||||
boost::unordered::detail::ptr_bucket
|
boost::unordered::detail::ptr_bucket
|
||||||
{
|
{
|
||||||
typedef boost::unordered::detail::ptr_bucket bucket_base;
|
typedef boost::unordered::detail::ptr_bucket bucket_base;
|
||||||
|
typedef bucket_base node_base;
|
||||||
typedef ptr_bucket* link_pointer;
|
typedef ptr_bucket* link_pointer;
|
||||||
|
|
||||||
std::size_t hash_;
|
std::size_t hash_;
|
||||||
|
|
||||||
|
#if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
|
||||||
|
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
|
||||||
|
ptr_node(BOOST_UNORDERED_EMPLACE_ARGS) :
|
||||||
|
bucket_base(),
|
||||||
|
hash_(0)
|
||||||
|
{
|
||||||
|
boost::unordered::detail::construct_impl(
|
||||||
|
this->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
~ptr_node() {
|
||||||
|
boost::unordered::detail::destroy(this->value_ptr());
|
||||||
|
}
|
||||||
|
#else
|
||||||
ptr_node() :
|
ptr_node() :
|
||||||
bucket_base(),
|
bucket_base(),
|
||||||
hash_(0)
|
hash_(0)
|
||||||
{}
|
{}
|
||||||
|
#endif
|
||||||
|
|
||||||
void init(link_pointer)
|
void init(link_pointer)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user