Introducing allocator_traits and pointer_traits changes into several libraries.

[SVN r76106]
This commit is contained in:
Ion Gaztañaga
2011-12-22 20:08:24 +00:00
parent 5247083184
commit 935a534713
41 changed files with 4304 additions and 2448 deletions
@@ -0,0 +1,381 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Pablo Halpern 2009. 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)
//
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-2011. 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)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP
#define BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/container/allocator/memory_util.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/move/move.hpp>
#include <limits> //numeric_limits<>::max()
#include <new> //placement new
#include <memory> //std::allocator
#include <boost/container/detail/preprocessor.hpp>
///@cond
namespace boost {
namespace container {
namespace container_detail {
//workaround needed for C++03 compilers with no construct()
//supporting rvalue references
template<class A>
struct is_std_allocator
{ static const bool value = false; };
template<class T>
struct is_std_allocator< std::allocator<T> >
{ static const bool value = true; };
} //namespace container_detail {
///@endcond
template <typename Alloc>
struct allocator_traits
{
//allocator_type
typedef Alloc allocator_type;
//value_type
typedef typename Alloc::value_type value_type;
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//!Alloc::pointer if such a type exists; otherwise, value_type*
//!
typedef unspecified pointer;
//!Alloc::const_pointer if such a type exists ; otherwise, pointer_traits<pointer>::rebind<const
//!
typedef unspecified const_pointer;
//!Non-standard extension
//!Alloc::reference if such a type exists; otherwise, value_type&
typedef unspecified pointer;
//!Non-standard extension
//!Alloc::const_reference if such a type exists ; otherwise, const value_type&
typedef unspecified const_pointer;
//!Alloc::void_pointer if such a type exists ; otherwise, pointer_traits<pointer>::rebind<void>.
//!
typedef unspecified void_pointer;
//!Alloc::const_void_pointer if such a type exists ; otherwis e, pointer_traits<pointer>::rebind<const
//!
typedef unspecified const_void_pointer;
//!Alloc::difference_type if such a type exists ; otherwise, pointer_traits<pointer>::difference_type.
//!
typedef unspecified difference_type;
//!Alloc::size_type if such a type exists ; otherwise, make_unsigned<difference_type>::type
//!
typedef unspecified size_type;
//!Alloc::propagate_on_container_copy_assignment if such a type exists, otherwise an integral_constant
//!type with internal constant static member <pre>value</pre> == false.
typedef unspecified propagate_on_container_copy_assignment;
//!Alloc::propagate_on_container_move_assignment if such a type exists, otherwise an integral_constant
//!type with internal constant static member <pre>value</pre> == false.
typedef unspecified propagate_on_container_move_assignment;
//!Alloc::propagate_on_container_swap if such a type exists, otherwise an integral_constant
//!type with internal constant static member <pre>value</pre> == false.
typedef unspecified propagate_on_container_swap;
//!Defines an allocator: Alloc::rebind<T>::other if such a type exists; otherwise, Alloc<T, Args>
//!if Alloc is a class template instantiation of the form Alloc<U, Args>, where Args is zero or
//!more type arguments ; otherwise, the instantiation of rebind_alloc is ill-formed.
//!
//!In C++03 compilers <pre>rebind_alloc</pre> is a struct derived from an allocator
//!deduced by previously detailed rules.
template <class T> using rebind_alloc = unspecified;
//!In C++03 compilers <pre>rebind_traits</pre> is a struct derived from
//!<pre>allocator_traits<OtherAlloc><pre>, where `OtherAlloc` is
//!the allocator deduced by rules explained in `rebind_alloc`.
template <class T> using rebind_traits = allocator_traits<rebind_alloc<T> >;
//!Non-standard extension: Portable allocator rebind for C++03 and C++11 compilers.
//!`type` is an allocator related to Alloc deduced deduced by rules explained in `rebind_alloc`.
template <class T>
struct portable_rebind_alloc
{ typedef unspecified_type type; };
#else
//pointer
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
pointer, value_type*)
pointer;
//const_pointer
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
const_pointer, typename boost::intrusive::pointer_traits<pointer>::template
rebind_pointer<const value_type>::type)
const_pointer;
//reference
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
reference, value_type&)
reference;
//const_reference
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
const_reference, const value_type&)
const_reference;
//void_pointer
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
void_pointer, typename boost::intrusive::pointer_traits<pointer>::template
rebind_pointer<void>::type)
void_pointer;
//const_void_pointer
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
const_void_pointer, typename boost::intrusive::pointer_traits<pointer>::template
rebind_pointer<const void>::type)
const_void_pointer;
//difference_type
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
difference_type, std::ptrdiff_t)
difference_type;
//size_type
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
size_type, std::size_t)
size_type;
//propagate_on_container_copy_assignment
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
propagate_on_container_copy_assignment, boost::false_type)
propagate_on_container_copy_assignment;
//propagate_on_container_move_assignment
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
propagate_on_container_move_assignment, boost::false_type)
propagate_on_container_move_assignment;
//propagate_on_container_swap
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
propagate_on_container_swap, boost::false_type)
propagate_on_container_swap;
#if !defined(BOOST_NO_TEMPLATE_ALIASES)
//C++11
template <typename T> using rebind_alloc = boost::intrusive::detail::type_rebinder<Alloc, T>::type;
template <typename T> using rebind_traits = allocator_traits< rebind_alloc<T> >;
#else //!defined(BOOST_NO_TEMPLATE_ALIASES)
//Some workaround for C++03 or C++11 compilers with no template aliases
template <typename T>
struct rebind_alloc : boost::intrusive::detail::type_rebinder<Alloc,T>::type
{
typedef typename boost::intrusive::detail::type_rebinder<Alloc,T>::type Base;
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template <typename... Args>
rebind_alloc(Args&&... args)
: Base(boost::forward<Args>(args)...)
{}
#else //!defined(BOOST_NO_VARIADIC_TEMPLATES)
#define BOOST_PP_LOCAL_MACRO(n) \
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
rebind_alloc(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
: Base(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)) \
{} \
//
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif //!defined(BOOST_NO_VARIADIC_TEMPLATES)
};
template <typename T>
struct rebind_traits
: allocator_traits<typename boost::intrusive::detail::type_rebinder<Alloc, T>::type>
{};
#endif //!defined(BOOST_NO_TEMPLATE_ALIASES)
template <class T>
struct portable_rebind_alloc
{ typedef typename boost::intrusive::detail::type_rebinder<Alloc, T>::type type; };
#endif //BOOST_CONTAINER_DOXYGEN_INVOKED
//!<b>Returns</b>: a.allocate(n)
//!
static pointer allocate(Alloc &a, size_type n)
{ return a.allocate(n); }
//!<b>Returns</b>: a.deallocate(p, n)
//!
//!<b>Throws</b>: Nothing
static void deallocate(Alloc &a, pointer p, size_type n)
{ return a.deallocate(p, n); }
//!<b>Effects</b>: calls `a.construct(p, std::forward<Args>(args)...)` if that call is well-formed;
//!otherwise, invokes `::new (static_cast<void*>(p)) T(std::forward<Args>(args)...)`
static pointer allocate(Alloc &a, size_type n, const_void_pointer p)
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_allocate
<Alloc, const size_type, const const_void_pointer>::value;
::boost::integral_constant<bool, value> flag;
return allocator_traits::priv_allocate(flag, a, n, p);
}
//!<b>Effects</b>: calls a.destroy(p) if that call is well-formed;
//!otherwise, invokes `p->~T()`.
template<class T>
static void destroy(Alloc &a, T*p)
{
typedef T* destroy_pointer;
const bool value = boost::container::container_detail::
has_member_function_callable_with_destroy
<Alloc, const destroy_pointer>::value;
::boost::integral_constant<bool, value> flag;
allocator_traits::priv_destroy(flag, a, p);
}
//!<b>Returns</b>: a.max_size() if that expression is well-formed; otherwise,
//!`numeric_limits<size_type>::max()`.
static size_type max_size(const Alloc &a)
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_max_size
<const Alloc>::value;
::boost::integral_constant<bool, value> flag;
return allocator_traits::priv_max_size(flag, a);
}
//!<b>Returns</b>: a.select_on_container_copy_construction() if that expres sion is well- formed;
//!otherwise, a.
static Alloc select_on_container_copy_construction(const Alloc &a)
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_select_on_container_copy_construction
<const Alloc>::value;
::boost::integral_constant<bool, value> flag;
return allocator_traits::priv_select_on_container_copy_construction(flag, a);
}
#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//!Effects: calls a.construct(p, std::forward<Args>(args)...) if that call is well-formed;
//!otherwise, invokes `::new (static_cast<void*>(p)) T(std::forward<Args>(args)...)`
template <class T, class ...Args>
static void construct(Alloc & a, T* p, Args&&... args)
{
::boost::integral_constant<bool, container_detail::is_std_allocator<Alloc>::value> flag;
allocator_traits::priv_construct(flag, a, p, ::boost::forward<Args>(args)...);
}
#endif
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
private:
static pointer priv_allocate(boost::true_type, Alloc &a, size_type n, const_void_pointer p)
{ return a.allocate(n, p); }
static pointer priv_allocate(boost::false_type, Alloc &a, size_type n, const_void_pointer)
{ return allocator_traits::allocate(a, n); }
template<class T>
static void priv_destroy(boost::true_type, Alloc &a, T* p)
{ a.destroy(p); }
template<class T>
static void priv_destroy(boost::false_type, Alloc &, T* p)
{ p->~T(); (void)p; }
static size_type priv_max_size(boost::true_type, const Alloc &a)
{ return a.max_size(); }
static size_type priv_max_size(boost::false_type, const Alloc &)
{ return (std::numeric_limits<size_type>::max)(); }
static Alloc priv_select_on_container_copy_construction(boost::true_type, const Alloc &a)
{ return a.select_on_container_copy_construction(); }
static Alloc priv_select_on_container_copy_construction(boost::false_type, const Alloc &a)
{ return a; }
#if defined(BOOST_CONTAINER_PERFECT_FORWARDING)
template<class T, class ...Args>
static void priv_construct(boost::false_type, Alloc &a, T *p, Args && ...args)
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_construct
< Alloc, T*, Args... >::value;
::boost::integral_constant<bool, value> flag;
priv_construct_dispatch2(flag, a, p, ::boost::forward<Args>(args)...);
}
template<class T, class ...Args>
static void priv_construct(boost::true_type, Alloc &a, T *p, Args && ...args)
{
priv_construct_dispatch2(boost::false_type(), a, p, ::boost::forward<Args>(args)...);
}
template<class T, class ...Args>
static void priv_construct_dispatch2(boost::true_type, Alloc &a, T *p, Args && ...args)
{ a.construct( p, ::boost::forward<Args>(args)...); }
template<class T, class ...Args>
static void priv_construct_dispatch2(boost::false_type, Alloc &, T *p, Args && ...args)
{ ::new((void*)p) T(::boost::forward<Args>(args)...); }
#else
public:
#define BOOST_PP_LOCAL_MACRO(n) \
template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
static void construct(Alloc &a, T *p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
{ \
::boost::integral_constant<bool, container_detail::is_std_allocator<Alloc>::value> flag; \
allocator_traits::priv_construct(flag, a, p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
} \
//
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
private:
#define BOOST_PP_LOCAL_MACRO(n) \
template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
static void priv_construct(boost::false_type, Alloc &a, T *p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_)) \
{ \
const bool value = \
boost::container::container_detail::has_member_function_callable_with_construct \
< Alloc, T* BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_FWD_TYPE, _) >::value; \
::boost::integral_constant<bool, value> flag; \
priv_construct_dispatch2(flag, a, p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
} \
\
template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
static void priv_construct(boost::true_type, Alloc &a, T *p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_)) \
{ \
priv_construct_dispatch2(boost::false_type(), a, p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
} \
\
template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
static void priv_construct_dispatch2(boost::true_type, Alloc &a, T *p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_)) \
{ a.construct( p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); } \
\
template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
static void priv_construct_dispatch2(boost::false_type, Alloc &, T *p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
{ ::new((void*)p) T(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \
//
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif //BOOST_CONTAINER_PERFECT_FORWARDING
#endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
///@endcond
};
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif // ! defined(BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP)
@@ -0,0 +1,77 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-2011. 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)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_ALLOCATOR_MEMORY_UTIL_HPP
#define BOOST_CONTAINER_ALLOCATOR_MEMORY_UTIL_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/preprocessor.hpp>
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME allocate
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 2, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME destroy
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 3, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME max_size
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 0, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME select_on_container_copy_construction
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 0, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME construct
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS+1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
namespace boost {
namespace container {
namespace container_detail {
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(pointer);
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_pointer);
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reference);
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_reference);
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(void_pointer);
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_void_pointer);
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(size_type);
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment);
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(difference_type);
} //namespace container_detail {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif // ! defined(BOOST_CONTAINER_ALLOCATOR_MEMORY_UTIL_HPP)
@@ -0,0 +1,651 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Pablo Halpern 2009. 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)
//
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-2011. 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)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP
#define BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/allocator/allocator_traits.hpp>
#include <boost/type_traits.hpp>
#include <utility>
namespace boost { namespace container {
template <typename OuterAlloc, typename... InnerAllocs>
class scoped_allocator_adaptor;
template <typename OuterAlloc, typename... InnerAllocs>
scoped_allocator_adaptor<OuterAlloc, InnerAllocs...> make_scoped();
template <typename OuterAlloc, typename... InnerAllocs>
class scoped_allocator_adaptor_base : public OuterAlloc
{
typedef allocator_traits<OuterAlloc> OuterTraits;
public:
// Workaround for inability of gcc-4.4.1 to expand InnerAllocs...
// typedef scoped_allocator_adaptor<InnerAllocs...> inner_allocator_type;
typedef decltype(make_scoped<InnerAllocs...>()) inner_allocator_type;
scoped_allocator_adaptor_base();
template <typename OuterA2>
scoped_allocator_adaptor_base(OuterA2&& outerAlloc, const InnerAllocs&... innerAllocs);
template <typename OuterA2>
scoped_allocator_adaptor_base(const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other);
template <typename OuterA2>
scoped_allocator_adaptor_base(scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other);
inner_allocator_type& inner_allocator()
{ return _M_inner_allocs; }
inner_allocator_type const& inner_allocator() const
{ return _M_inner_allocs; }
// Allocator propagation functions.
scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>
select_on_container_copy_construction() const;
typedef std::integral_constant<
bool,
OuterTraits::propagate_on_container_copy_assignment::value ||
inner_allocator_type::propagate_on_container_copy_assignment::value
> propagate_on_container_copy_assignment;
typedef std::integral_constant<
bool,
OuterTraits::propagate_on_container_move_assignment::value ||
inner_allocator_type::propagate_on_container_move_assignment::value
> propagate_on_container_move_assignment;
typedef std::integral_constant<
bool,
OuterTraits::propagate_on_container_swap::value ||
inner_allocator_type::propagate_on_container_swap::value
> propagate_on_container_swap;
private:
inner_allocator_type _M_inner_allocs;
};
// Specialization with only one parameter.
template <typename OuterAlloc>
class scoped_allocator_adaptor_base<OuterAlloc> : public OuterAlloc
{
typedef allocator_traits<OuterAlloc> OuterTraits;
public:
typedef scoped_allocator_adaptor<OuterAlloc> inner_allocator_type;
scoped_allocator_adaptor_base();
template <typename OuterA2>
scoped_allocator_adaptor_base(OuterA2&& outerAlloc);
template <typename OuterA2>
scoped_allocator_adaptor_base(const scoped_allocator_adaptor<OuterA2>& other);
template <typename OuterA2>
scoped_allocator_adaptor_base(scoped_allocator_adaptor<OuterA2>&& other);
inner_allocator_type& inner_allocator()
{ return static_cast<inner_allocator_type&>(*this); }
inner_allocator_type const& inner_allocator() const
{ return static_cast<const inner_allocator_type&>(*this); }
// Allocator propagation functions.
scoped_allocator_adaptor<OuterAlloc>
select_on_container_copy_construction() const;
typedef typename OuterTraits::propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
typedef typename OuterTraits::propagate_on_container_move_assignment propagate_on_container_move_assignment;
typedef typename OuterTraits::propagate_on_container_swap propagate_on_container_swap;
};
template <typename OuterAlloc, typename... InnerAllocs>
class scoped_allocator_adaptor
: public scoped_allocator_adaptor_base<OuterAlloc, InnerAllocs...>
{
typedef scoped_allocator_adaptor_base<OuterAlloc, InnerAllocs...> _Base;
typedef allocator_traits<OuterAlloc> _Traits;
public:
typedef OuterAlloc outer_allocator_type;
typedef typename _Base::inner_allocator_type inner_allocator_type;
typedef typename allocator_traits<OuterAlloc>::size_type size_type;
typedef typename allocator_traits<OuterAlloc>::difference_type difference_type;
typedef typename allocator_traits<OuterAlloc>::pointer pointer;
typedef typename allocator_traits<OuterAlloc>::const_pointer const_pointer;
typedef typename allocator_traits<OuterAlloc>::void_pointer void_pointer;
typedef typename allocator_traits<OuterAlloc>::const_void_pointer const_void_pointer;
typedef typename allocator_traits<OuterAlloc>::value_type value_type;
template <typename Tp>
struct rebind {
typedef typename allocator_traits<OuterAlloc>::template rebind_traits<Tp> rebound_traits;
typedef typename rebound_traits::allocator_type rebound_outer; // exposition only
typedef scoped_allocator_adaptor<rebound_outer, InnerAllocs...> other;
};
scoped_allocator_adaptor();
scoped_allocator_adaptor(const scoped_allocator_adaptor& other);
template <typename OuterA2>
scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other);
template <typename OuterA2>
scoped_allocator_adaptor(scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other);
template <typename OuterA2>
scoped_allocator_adaptor(OuterA2&& outerAlloc, const InnerAllocs&... innerAllocs);
~scoped_allocator_adaptor();
inner_allocator_type & inner_allocator()
{ return _Base::inner_allocator(); }
inner_allocator_type const& inner_allocator() const
{ return _Base::inner_allocator(); }
outer_allocator_type & outer_allocator()
{ return *this; }
outer_allocator_type const& outer_allocator() const
{ return *this; }
pointer allocate(size_type n);
pointer allocate(size_type n, const_void_pointer hint);
void deallocate(pointer p, size_type n);
size_type max_size() const;
template <typename T, typename... Args>
void construct(T* p, Args&&... args);
// Specializations to pass inner_allocator to pair::first and pair::second
template <class T1, class T2>
void construct(std::pair<T1,T2>* p);
template <class T1, class T2, class U, class V>
void construct(std::pair<T1,T2>* p, U&& x, V&& y);
template <class T1, class T2, class U, class V>
void construct(std::pair<T1,T2>* p, const std::pair<U, V>& pr);
template <class T1, class T2, class U, class V>
void construct(std::pair<T1,T2>* p, std::pair<U, V>&& pr);
template <typename T>
void destroy(T* p);
};
template <typename OuterA1, typename OuterA2, typename... InnerAllocs>
inline
bool operator==(const scoped_allocator_adaptor<OuterA1,InnerAllocs...>& a,
const scoped_allocator_adaptor<OuterA2,InnerAllocs...>& b);
template <typename OuterA1, typename OuterA2, typename... InnerAllocs>
inline
bool operator!=(const scoped_allocator_adaptor<OuterA1,InnerAllocs...>& a,
const scoped_allocator_adaptor<OuterA2,InnerAllocs...>& b);
///////////////////////////////////////////////////////////////////////////////
// Implementation of scoped_allocator_adaptor_base<OuterAlloc, InnerAllocs...>
///////////////////////////////////////////////////////////////////////////////
template <typename OuterAlloc, typename... InnerAllocs>
inline
scoped_allocator_adaptor_base<OuterAlloc, InnerAllocs...>::
scoped_allocator_adaptor_base()
{
}
template <typename OuterAlloc, typename... InnerAllocs>
template <typename OuterA2>
scoped_allocator_adaptor_base<OuterAlloc, InnerAllocs...>::
scoped_allocator_adaptor_base(OuterA2&& outerAlloc,
const InnerAllocs&... innerAllocs)
: OuterAlloc(std::forward<OuterA2>(outerAlloc))
, _M_inner_allocs(innerAllocs...)
{
}
template <typename OuterAlloc, typename... InnerAllocs>
template <typename OuterA2>
scoped_allocator_adaptor_base<OuterAlloc, InnerAllocs...>::
scoped_allocator_adaptor_base(
const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other)
: OuterAlloc(other.outer_allocator())
, _M_inner_allocs(other.inner_allocator())
{
}
template <typename OuterAlloc, typename... InnerAllocs>
template <typename OuterA2>
scoped_allocator_adaptor_base<OuterAlloc, InnerAllocs...>::
scoped_allocator_adaptor_base(
scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other)
: OuterAlloc(std::move(other.outer_allocator()))
, _M_inner_allocs(std::move(other.inner_allocator()))
{
}
template <typename OuterAlloc, typename... InnerAllocs>
inline
scoped_allocator_adaptor<OuterAlloc,InnerAllocs...>
scoped_allocator_adaptor_base<OuterAlloc,InnerAllocs...>::
select_on_container_copy_construction() const
{
return scoped_allocator_adaptor<OuterAlloc,InnerAllocs...>(
allocator_traits<OuterAlloc>::select_on_container_copy_construction(
this->outer_allocator()),
allocator_traits<inner_allocator_type>::select_on_container_copy_construction(
this->inner_allocator()));
}
///////////////////////////////////////////////////////////////////////////////
// Implementation of scoped_allocator_adaptor_base<OuterAlloc> specialization
///////////////////////////////////////////////////////////////////////////////
template <typename OuterAlloc>
inline
scoped_allocator_adaptor_base<OuterAlloc>::
scoped_allocator_adaptor_base()
{
}
template <typename OuterAlloc>
template <typename OuterA2>
scoped_allocator_adaptor_base<OuterAlloc>::
scoped_allocator_adaptor_base(OuterA2&& outerAlloc)
: OuterAlloc(std::forward<OuterA2>(outerAlloc))
{
}
template <typename OuterAlloc>
template <typename OuterA2>
scoped_allocator_adaptor_base<OuterAlloc>::
scoped_allocator_adaptor_base(
const scoped_allocator_adaptor<OuterA2>& other)
: OuterAlloc(other.outer_allocator())
{
}
template <typename OuterAlloc>
template <typename OuterA2>
scoped_allocator_adaptor_base<OuterAlloc>::
scoped_allocator_adaptor_base(
scoped_allocator_adaptor<OuterA2>&& other)
: OuterAlloc(std::move(other.outer_allocator()))
{
}
// template <typename OuterAlloc>
// inline
// scoped_allocator_adaptor<OuterAlloc>&
// scoped_allocator_adaptor_base<OuterAlloc>::inner_allocator()
// {
// return *this;
// }
// template <typename OuterAlloc>
// inline
// scoped_allocator_adaptor<OuterAlloc> const&
// scoped_allocator_adaptor_base<OuterAlloc>::inner_allocator() cosnt
// {
// return *this;
// }
template <typename OuterAlloc>
inline
scoped_allocator_adaptor<OuterAlloc>
scoped_allocator_adaptor_base<OuterAlloc>::
select_on_container_copy_construction() const
{
return
allocator_traits<OuterAlloc>::select_on_container_copy_construction(
this->outer_allocator());
}
///////////////////////////////////////////////////////////////////////////////
// Implementation of scoped_allocator_adaptor details
///////////////////////////////////////////////////////////////////////////////
namespace __details {
// Overload resolution for __has_ctor resolves to this function
// when _Tp is constructible with _Args. Returns true_type().
static void* __void_p; // Declared but not defined
template <typename _Tp, typename... _Args>
inline
auto __has_ctor(int, _Args&&... __args) ->
decltype((new (__void_p) _Tp(__args...), std::true_type()))
{ return std::true_type(); }
// Overload resolution for __has_ctor resolves to this function
// when _Tp is not constructible with _Args. Returns false_type().
template <typename _Tp, typename... _Args>
auto __has_ctor(_LowPriorityConversion<int>, _Args&&...) ->
std::false_type
{ return std::false_type(); }
template <typename _Alloc>
struct __is_scoped_allocator_imp {
template <typename T>
static char test(int, typename T::outer_allocator_type*);
template <typename T>
static int test(_LowPriorityConversion<int>, void*);
static const bool value = (1 == sizeof(test<_Alloc>(0, 0)));
};
template <typename _Alloc>
struct __is_scoped_allocator
: std::integral_constant<bool, __is_scoped_allocator_imp<_Alloc>::value>
{
};
#if 0
// Called when outer_allocator_type is not a scoped allocator
// (recursion stop).
template <typename _Alloc>
inline
auto __outermost_alloc(_LowPriorityConversion<int>, _Alloc& __a) ->
_Alloc&
{
return __a;
}
// Called when outer_allocator_type is a scoped allocator to
// return the outermost allocator type.
template <typename _Alloc>
inline auto __outermost_alloc(int, _Alloc& __a) ->
decltype(__outermost_alloc(0,__a.outer_allocator()))
{
return __a.outer_allocator();
}
#endif
template <typename _Ignore, typename _OuterAlloc,
typename _InnerAlloc, typename _Tp, typename... _Args>
inline void __dispatch_scoped_construct(std::false_type __uses_alloc,
_Ignore __use_alloc_prefix,
_OuterAlloc& __outer_alloc,
_InnerAlloc& __inner_alloc,
_Tp* __p, _Args&&... __args)
{
// _Tp doesn't use allocators. Construct without an
// allocator argument.
allocator_traits<_OuterAlloc>::construct(__outer_alloc, __p,
std::forward<_Args>(__args)...);
}
template <typename _OuterAlloc,
typename _InnerAlloc, typename _Tp, typename... _Args>
inline void __dispatch_scoped_construct(std::true_type __uses_alloc,
std::true_type __use_alloc_prefix,
_OuterAlloc& __outer_alloc,
_InnerAlloc& __inner_alloc,
_Tp* __p, _Args&&... __args)
{
// _Tp doesn't use allocators. Construct without an
// allocator argument.
allocator_traits<_OuterAlloc>::construct(__outer_alloc, __p,
allocator_arg, __inner_alloc,
std::forward<_Args>(__args)...);
}
template <typename _OuterAlloc,
typename _InnerAlloc, typename _Tp, typename... _Args>
inline void __dispatch_scoped_construct(std::true_type __uses_alloc,
std::false_type __use_alloc_prefix,
_OuterAlloc& __outer_alloc,
_InnerAlloc& __inner_alloc,
_Tp* __p, _Args&&... __args)
{
// If _Tp uses an allocator compatible with _InnerAlloc,
// but the specific constructor does not have a variant that
// takes an allocator argument, then program is malformed.
// static_assert(has_constructor<_Tp, _Args...>::value,
// "Cannot pass inner allocator to this constructor");
allocator_traits<_OuterAlloc>::construct(
__outer_alloc, __p, std::forward<_Args>(__args)...,
__inner_alloc);
}
template <typename _OuterAlloc, typename _InnerAlloc,
typename _Tp, typename... _Args>
inline void __do_scoped_construct(std::false_type __scoped_outer,
_OuterAlloc& __outer_alloc,
_InnerAlloc& __inner_alloc,
_Tp* __p, _Args&&... __args)
{
// Dispatch construction to the correct __dispatch_scoped_construct()
// function based on whether _Tp uses an allocator of type
// _InnerAlloc and, if so, whether there exists the following
// constructor:
// _Tp(allocator_arg_t, _InnerAlloc, Args...).
auto __uses_alloc = uses_allocator<_Tp, _InnerAlloc>();
auto __use_alloc_prefix = __has_ctor<_Tp>(0, allocator_arg,
__inner_alloc,
std::forward<_Args>(__args)...);
__dispatch_scoped_construct(__uses_alloc, __use_alloc_prefix,
__outer_alloc,
__inner_alloc,
__p, std::forward<_Args>(__args)...);
}
template <typename _OuterAlloc, typename _InnerAlloc,
typename _Tp, typename... _Args>
void __do_scoped_construct(std::true_type __scoped_outer,
_OuterAlloc& __outer_alloc,
_InnerAlloc& __inner_alloc,
_Tp* __p, _Args&&... __args)
{
// Use outermost allocator if __outer_alloc is scoped
typedef typename _OuterAlloc::outer_allocator_type outerouter;
__do_scoped_construct(__is_scoped_allocator<outerouter>(),
__outer_alloc.outer_allocator(),
__inner_alloc,
__p, std::forward<_Args>(__args)...);
}
} // end namespace __details
///////////////////////////////////////////////////////////////////////////////
// Implementation of scoped_allocator_adaptor
///////////////////////////////////////////////////////////////////////////////
template <typename OuterAlloc, typename... InnerAllocs>
scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>::
scoped_allocator_adaptor()
{
}
template <typename OuterAlloc, typename... InnerAllocs>
scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>::
scoped_allocator_adaptor(const scoped_allocator_adaptor& other)
: _Base(other)
{
}
template <typename OuterAlloc, typename... InnerAllocs>
template <typename OuterA2>
scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>::
scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2,
InnerAllocs...>& other)
: _Base(other)
{
}
template <typename OuterAlloc, typename... InnerAllocs>
template <typename OuterA2>
scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>::
scoped_allocator_adaptor(scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other)
: _Base(std::move(other))
{
}
template <typename OuterAlloc, typename... InnerAllocs>
template <typename OuterA2>
scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>::
scoped_allocator_adaptor(OuterA2&& outerAlloc, const InnerAllocs&... innerAllocs)
: _Base(std::forward<OuterA2>(outerAlloc), innerAllocs...)
{
}
template <typename OuterAlloc, typename... InnerAllocs>
scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>::
~scoped_allocator_adaptor()
{
}
template <typename OuterAlloc, typename... InnerAllocs>
inline typename allocator_traits<OuterAlloc>::pointer
scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>::
allocate(size_type n)
{
return allocator_traits<OuterAlloc>::allocate(outer_allocator(), n);
}
template <typename OuterAlloc, typename... InnerAllocs>
inline typename allocator_traits<OuterAlloc>::pointer
scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>::
allocate(size_type n, const_void_pointer hint)
{
return allocator_traits<OuterAlloc>::allocate(outer_allocator(), n, hint);
}
template <typename OuterAlloc, typename... InnerAllocs>
inline void scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>::
deallocate(pointer p, size_type n)
{
allocator_traits<OuterAlloc>::deallocate(outer_allocator(), p, n);
}
template <typename OuterAlloc, typename... InnerAllocs>
inline typename allocator_traits<OuterAlloc>::size_type
scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>::max_size() const
{
return allocator_traits<OuterAlloc>::max_size(outer_allocator());
}
template <typename OuterAlloc, typename... InnerAllocs>
template <typename T>
inline void scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>::
destroy(T* p)
{
allocator_traits<OuterAlloc>::destroy(outer_allocator(), p);
}
template <typename OuterAlloc, typename... InnerAllocs>
template <typename T, typename... Args>
inline
void scoped_allocator_adaptor<OuterAlloc,InnerAllocs...>::construct(T* p,
Args&&... args)
{
__do_scoped_construct(__details::__is_scoped_allocator<OuterAlloc>(),
this->outer_allocator(), this->inner_allocator(),
p, std::forward<Args>(args)...);
}
template <typename OuterAlloc, typename... InnerAllocs>
template <class T1, class T2>
void scoped_allocator_adaptor<OuterAlloc,InnerAllocs...>::construct(
std::pair<T1,T2>* p)
{
construct(addressof(p->first));
try {
construct(addressof(p->second));
}
catch (...) {
destroy(addressof(p->first));
throw;
}
}
template <typename OuterAlloc, typename... InnerAllocs>
template <class T1, class T2, class U, class V>
void scoped_allocator_adaptor<OuterAlloc,InnerAllocs...>::construct(
std::pair<T1,T2>* p, U&& x, V&& y)
{
construct(addressof(p->first), std::forward<U>(x));
try {
construct(addressof(p->second), std::forward<V>(y));
}
catch (...) {
destroy(addressof(p->first));
throw;
}
}
template <typename OuterAlloc, typename... InnerAllocs>
template <class T1, class T2, class U, class V>
void scoped_allocator_adaptor<OuterAlloc,InnerAllocs...>::construct(
std::pair<T1,T2>* p, const std::pair<U, V>& pr)
{
construct(addressof(p->first), pr.first);
try {
construct(addressof(p->second), pr.second);
}
catch (...) {
destroy(addressof(p->first));
throw;
}
}
template <typename OuterAlloc, typename... InnerAllocs>
template <class T1, class T2, class U, class V>
void scoped_allocator_adaptor<OuterAlloc,InnerAllocs...>::construct(
std::pair<T1,T2>* p, std::pair<U, V>&& pr)
{
construct(addressof(p->first), std::move(pr.first));
try {
construct(addressof(p->second), std::move(pr.second));
}
catch (...) {
destroy(addressof(p->first));
throw;
}
}
template <typename OuterA1, typename OuterA2, typename... InnerAllocs>
inline
bool operator==(const scoped_allocator_adaptor<OuterA1,InnerAllocs...>& a,
const scoped_allocator_adaptor<OuterA2,InnerAllocs...>& b)
{
return a.outer_allocator() == b.outer_allocator()
&& a.inner_allocator() == b.inner_allocator();
}
template <typename OuterA1, typename OuterA2>
inline
bool operator==(const scoped_allocator_adaptor<OuterA1>& a,
const scoped_allocator_adaptor<OuterA2>& b)
{
return a.outer_allocator() == b.outer_allocator();
}
template <typename OuterA1, typename OuterA2, typename... InnerAllocs>
inline
bool operator!=(const scoped_allocator_adaptor<OuterA1,InnerAllocs...>& a,
const scoped_allocator_adaptor<OuterA2,InnerAllocs...>& b)
{
return ! (a == b);
}
}} // namespace boost { namespace container {
#include <boost/container/detail/config_end.hpp>
#endif // BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP