Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // (C) Copyright Pablo Halpern 2009. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@101: // (C) Copyright Ion Gaztanaga 2011-2013. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // See http://www.boost.org/libs/container for documentation. Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: #ifndef BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP Chris@16: #define BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP Chris@16: Chris@16: #if defined (_MSC_VER) Chris@16: # pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@101: Chris@101: #include Chris@16: #include Chris@101: Chris@101: #include Chris@101: #include Chris@101: #include Chris@16: #include Chris@101: Chris@101: #include Chris@101: #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@101: #include Chris@101: #endif Chris@101: #include Chris@101: Chris@101: #include Chris@16: Chris@16: namespace boost { namespace container { Chris@16: Chris@101: //! Remark: if a specialization constructible_with_allocator_suffix::value is true, indicates that T may be constructed Chris@16: //! with an allocator as its last constructor argument. Ideally, all constructors of T (including the Chris@16: //! copy and move constructors) should have a variant that accepts a final argument of Chris@16: //! allocator_type. Chris@16: //! Chris@101: //! Requires: if a specialization constructible_with_allocator_suffix::value is true, T must have a nested type, Chris@16: //! allocator_type and at least one constructor for which allocator_type is the last Chris@16: //! parameter. If not all constructors of T can be called with a final allocator_type argument, Chris@16: //! and if T is used in a context where a container must call such a constructor, then the program is Chris@16: //! ill-formed. Chris@16: //! Chris@101: //! Chris@101: //! template > Chris@16: //! class Z { Chris@16: //! public: Chris@16: //! typedef Allocator allocator_type; Chris@16: //! Chris@16: //! // Default constructor with optional allocator suffix Chris@16: //! Z(const allocator_type& a = allocator_type()); Chris@16: //! Chris@16: //! // Copy constructor and allocator-extended copy constructor Chris@16: //! Z(const Z& zz); Chris@16: //! Z(const Z& zz, const allocator_type& a); Chris@16: //! }; Chris@16: //! Chris@16: //! // Specialize trait for class template Z Chris@16: //! template > Chris@101: //! struct constructible_with_allocator_suffix > Chris@101: //! { static const bool value = true; }; Chris@101: //! Chris@16: //! Chris@101: //! Note: This trait is a workaround inspired by "N2554: The Scoped A Model (Rev 2)" Chris@16: //! (Pablo Halpern, 2008-02-29) to backport the scoped allocator model to C++03, as Chris@16: //! in C++03 there is no mechanism to detect if a type can be constructed from arbitrary arguments. Chris@16: //! Applications aiming portability with several compilers should always define this trait. Chris@16: //! Chris@16: //! In conforming C++11 compilers or compilers supporting SFINAE expressions Chris@16: //! (when BOOST_NO_SFINAE_EXPR is NOT defined), this trait is ignored and C++11 rules will be used Chris@16: //! to detect if a type should be constructed with suffix or prefix allocator arguments. Chris@16: template Chris@16: struct constructible_with_allocator_suffix Chris@101: { static const bool value = false; }; Chris@16: Chris@101: //! Remark: if a specialization constructible_with_allocator_prefix::value is true, indicates that T may be constructed Chris@101: //! with allocator_arg and T::allocator_type as its first two constructor arguments. Chris@16: //! Ideally, all constructors of T (including the copy and move constructors) should have a variant Chris@16: //! that accepts these two initial arguments. Chris@16: //! Chris@101: //! Requires: specialization constructible_with_allocator_prefix::value is true, T must have a nested type, Chris@16: //! allocator_type and at least one constructor for which allocator_arg_t is the first Chris@16: //! parameter and allocator_type is the second parameter. If not all constructors of T can be Chris@16: //! called with these initial arguments, and if T is used in a context where a container must call such Chris@16: //! a constructor, then the program is ill-formed. Chris@16: //! Chris@101: //! Chris@16: //! template > Chris@16: //! class Y { Chris@16: //! public: Chris@16: //! typedef Allocator allocator_type; Chris@101: //! Chris@16: //! // Default constructor with and allocator-extended default constructor Chris@16: //! Y(); Chris@16: //! Y(allocator_arg_t, const allocator_type& a); Chris@101: //! Chris@16: //! // Copy constructor and allocator-extended copy constructor Chris@16: //! Y(const Y& yy); Chris@16: //! Y(allocator_arg_t, const allocator_type& a, const Y& yy); Chris@101: //! Chris@16: //! // Variadic constructor and allocator-extended variadic constructor Chris@16: //! template Y(Args&& args...); Chris@101: //! template Chris@101: //! Y(allocator_arg_t, const allocator_type& a, BOOST_FWD_REF(Args)... args); Chris@16: //! }; Chris@101: //! Chris@16: //! // Specialize trait for class template Y Chris@16: //! template > Chris@101: //! struct constructible_with_allocator_prefix > Chris@101: //! { static const bool value = true; }; Chris@101: //! Chris@101: //! Chris@16: //! Chris@16: //! Note: This trait is a workaround inspired by "N2554: The Scoped Allocator Model (Rev 2)" Chris@16: //! (Pablo Halpern, 2008-02-29) to backport the scoped allocator model to C++03, as Chris@16: //! in C++03 there is no mechanism to detect if a type can be constructed from arbitrary arguments. Chris@16: //! Applications aiming portability with several compilers should always define this trait. Chris@16: //! Chris@16: //! In conforming C++11 compilers or compilers supporting SFINAE expressions Chris@16: //! (when BOOST_NO_SFINAE_EXPR is NOT defined), this trait is ignored and C++11 rules will be used Chris@16: //! to detect if a type should be constructed with suffix or prefix allocator arguments. Chris@16: template Chris@16: struct constructible_with_allocator_prefix Chris@101: { static const bool value = false; }; Chris@16: Chris@101: #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: Chris@16: namespace container_detail { Chris@16: Chris@101: template Chris@16: struct uses_allocator_imp Chris@16: { Chris@16: // Use SFINAE (Substitution Failure Is Not An Error) to detect the Chris@101: // presence of an 'allocator_type' nested type convertilble from Allocator. Chris@101: private: Chris@101: typedef char yes_type; Chris@101: struct no_type{ char dummy[2]; }; Chris@16: Chris@16: // Match this function if TypeT::allocator_type exists and is Chris@101: // implicitly convertible from Allocator Chris@101: template Chris@101: static yes_type test(typename U::allocator_type); Chris@16: Chris@16: // Match this function if TypeT::allocator_type does not exist or is Chris@101: // not convertible from Allocator. Chris@16: template Chris@101: static no_type test(...); Chris@101: static Allocator alloc; // Declared but not defined Chris@16: Chris@16: public: Chris@101: static const bool value = sizeof(test(alloc)) == sizeof(yes_type); Chris@16: }; Chris@16: Chris@16: } //namespace container_detail { Chris@16: Chris@101: #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: Chris@16: //! Remark: Automatically detects if T has a nested allocator_type that is convertible from Chris@101: //! Allocator. Meets the BinaryTypeTrait requirements ([meta.rqmts] 20.4.1). A program may Chris@101: //! specialize this type to define uses_allocator::value as true for a T of user-defined type if T does not Chris@101: //! have a nested allocator_type but is nonetheless constructible using the specified Allocator. Chris@16: //! Chris@101: //! Result: uses_allocator::value== true if Convertible, Chris@101: //! false otherwise. Chris@101: template Chris@16: struct uses_allocator Chris@101: : container_detail::uses_allocator_imp Chris@16: {}; Chris@16: Chris@101: #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: Chris@16: namespace container_detail { Chris@16: Chris@101: template Chris@16: struct is_scoped_allocator_imp Chris@16: { Chris@101: typedef char yes_type; Chris@101: struct no_type{ char dummy[2]; }; Chris@16: Chris@16: template Chris@101: static yes_type test(typename T::outer_allocator_type*); Chris@16: Chris@101: template Chris@101: static int test(...); Chris@101: Chris@101: static const bool value = (sizeof(yes_type) == sizeof(test(0))); Chris@16: }; Chris@16: Chris@16: template::value > Chris@16: struct outermost_allocator_type_impl Chris@16: { Chris@16: typedef typename MaybeScopedAlloc::outer_allocator_type outer_type; Chris@16: typedef typename outermost_allocator_type_impl::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct outermost_allocator_type_impl Chris@16: { Chris@16: typedef MaybeScopedAlloc type; Chris@16: }; Chris@16: Chris@16: template::value > Chris@16: struct outermost_allocator_imp Chris@16: { Chris@16: typedef MaybeScopedAlloc type; Chris@16: Chris@16: static type &get(MaybeScopedAlloc &a) Chris@16: { return a; } Chris@16: Chris@16: static const type &get(const MaybeScopedAlloc &a) Chris@16: { return a; } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct outermost_allocator_imp Chris@16: { Chris@16: typedef typename MaybeScopedAlloc::outer_allocator_type outer_type; Chris@16: typedef typename outermost_allocator_type_impl::type type; Chris@16: Chris@16: static type &get(MaybeScopedAlloc &a) Chris@16: { return outermost_allocator_imp::get(a.outer_allocator()); } Chris@16: Chris@16: static const type &get(const MaybeScopedAlloc &a) Chris@16: { return outermost_allocator_imp::get(a.outer_allocator()); } Chris@16: }; Chris@16: Chris@16: } //namespace container_detail { Chris@16: Chris@101: template Chris@16: struct is_scoped_allocator Chris@101: : container_detail::is_scoped_allocator_imp Chris@16: {}; Chris@16: Chris@101: template Chris@16: struct outermost_allocator Chris@101: : container_detail::outermost_allocator_imp Chris@16: {}; Chris@16: Chris@101: template Chris@101: typename container_detail::outermost_allocator_imp::type & Chris@101: get_outermost_allocator(Allocator &a) Chris@101: { return container_detail::outermost_allocator_imp::get(a); } Chris@16: Chris@101: template Chris@101: const typename container_detail::outermost_allocator_imp::type & Chris@101: get_outermost_allocator(const Allocator &a) Chris@101: { return container_detail::outermost_allocator_imp::get(a); } Chris@16: Chris@16: namespace container_detail { Chris@16: Chris@16: // Check if we can detect is_convertible using advanced SFINAE expressions Chris@101: #if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@16: //! Code inspired by Mathias Gaunard's is_convertible.cpp found in the Boost mailing list Chris@16: //! http://boost.2283326.n4.nabble.com/type-traits-is-constructible-when-decltype-is-supported-td3575452.html Chris@16: //! Thanks Mathias! Chris@16: Chris@16: //With variadic templates, we need a single class to implement the trait Chris@16: template Chris@101: struct is_constructible Chris@16: { Chris@16: typedef char yes_type; Chris@16: struct no_type Chris@16: { char padding[2]; }; Chris@16: Chris@16: template Chris@16: struct dummy; Chris@16: Chris@16: template Chris@101: static decltype(X(boost::move_detail::declval()...), true_type()) test(int); Chris@16: Chris@16: template Chris@16: static no_type test(...); Chris@16: Chris@16: static const bool value = sizeof(test(0)) == sizeof(yes_type); Chris@16: }; Chris@16: Chris@16: template Chris@16: struct is_constructible_with_allocator_prefix Chris@16: : is_constructible Chris@16: {}; Chris@16: Chris@101: #else // #if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@16: //Without advanced SFINAE expressions, we can't use is_constructible Chris@16: //so backup to constructible_with_allocator_xxx Chris@16: Chris@16: #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@101: template Chris@16: struct is_constructible_with_allocator_prefix Chris@16: : constructible_with_allocator_prefix Chris@16: {}; Chris@101: Chris@101: template Chris@16: struct is_constructible_with_allocator_suffix Chris@16: : constructible_with_allocator_suffix Chris@101: {}; Chris@16: Chris@16: #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@101: template Chris@16: struct is_constructible_with_allocator_prefix Chris@16: : constructible_with_allocator_prefix Chris@16: {}; Chris@101: Chris@101: template Chris@16: struct is_constructible_with_allocator_suffix Chris@16: : constructible_with_allocator_suffix Chris@101: {}; Chris@16: Chris@16: #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@16: #endif // #if !defined(BOOST_NO_SFINAE_EXPR) Chris@16: Chris@16: #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@101: // allocator_arg_t Chris@16: template < typename OutermostAlloc Chris@16: , typename InnerAlloc Chris@16: , typename T Chris@16: , class ...Args Chris@16: > Chris@16: inline void dispatch_allocator_prefix_suffix Chris@101: ( true_type use_alloc_prefix, OutermostAlloc& outermost_alloc Chris@16: , InnerAlloc& inner_alloc, T* p, BOOST_FWD_REF(Args) ...args) Chris@16: { Chris@16: (void)use_alloc_prefix; Chris@16: allocator_traits::construct Chris@16: ( outermost_alloc, p, allocator_arg, inner_alloc, ::boost::forward(args)...); Chris@16: } Chris@16: Chris@101: // allocator suffix Chris@16: template < typename OutermostAlloc Chris@16: , typename InnerAlloc Chris@16: , typename T Chris@16: , class ...Args Chris@16: > Chris@16: inline void dispatch_allocator_prefix_suffix Chris@101: ( false_type use_alloc_prefix, OutermostAlloc& outermost_alloc Chris@16: , InnerAlloc &inner_alloc, T* p, BOOST_FWD_REF(Args)...args) Chris@16: { Chris@16: (void)use_alloc_prefix; Chris@16: allocator_traits::construct Chris@16: (outermost_alloc, p, ::boost::forward(args)..., inner_alloc); Chris@16: } Chris@16: Chris@16: template < typename OutermostAlloc Chris@16: , typename InnerAlloc Chris@16: , typename T Chris@16: , class ...Args Chris@16: > Chris@16: inline void dispatch_uses_allocator Chris@101: ( true_type uses_allocator, OutermostAlloc& outermost_alloc Chris@16: , InnerAlloc& inner_alloc, T* p, BOOST_FWD_REF(Args)...args) Chris@16: { Chris@16: (void)uses_allocator; Chris@16: //BOOST_STATIC_ASSERT((is_constructible_with_allocator_prefix::value || Chris@16: // is_constructible_with_allocator_suffix::value )); Chris@16: dispatch_allocator_prefix_suffix Chris@101: ( bool_< is_constructible_with_allocator_prefix::value>() Chris@16: , outermost_alloc, inner_alloc, p, ::boost::forward(args)...); Chris@16: } Chris@16: Chris@16: template < typename OutermostAlloc Chris@16: , typename InnerAlloc Chris@16: , typename T Chris@16: , class ...Args Chris@16: > Chris@16: inline void dispatch_uses_allocator Chris@101: ( false_type uses_allocator, OutermostAlloc & outermost_alloc Chris@16: , InnerAlloc & inner_alloc Chris@16: ,T* p, BOOST_FWD_REF(Args)...args) Chris@16: { Chris@16: (void)uses_allocator; (void)inner_alloc; Chris@16: allocator_traits::construct Chris@16: (outermost_alloc, p, ::boost::forward(args)...); Chris@16: } Chris@16: Chris@16: #else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@101: #define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \ Chris@101: template < typename OutermostAlloc, typename InnerAlloc, typename T\ Chris@101: BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \ Chris@101: inline void dispatch_allocator_prefix_suffix\ Chris@101: (true_type use_alloc_prefix, OutermostAlloc& outermost_alloc,\ Chris@101: InnerAlloc& inner_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ Chris@101: {\ Chris@101: (void)use_alloc_prefix,\ Chris@101: allocator_traits::construct\ Chris@101: (outermost_alloc, p, allocator_arg, inner_alloc BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ Chris@101: }\ Chris@101: \ Chris@101: template < typename OutermostAlloc, typename InnerAlloc, typename T\ Chris@101: BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\ Chris@101: inline void dispatch_allocator_prefix_suffix\ Chris@101: (false_type use_alloc_prefix, OutermostAlloc& outermost_alloc,\ Chris@101: InnerAlloc& inner_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ Chris@101: {\ Chris@101: (void)use_alloc_prefix;\ Chris@101: allocator_traits::construct\ Chris@101: (outermost_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N, inner_alloc);\ Chris@101: }\ Chris@101: \ Chris@101: template < typename OutermostAlloc, typename InnerAlloc, typename T\ Chris@101: BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\ Chris@101: inline void dispatch_uses_allocator\ Chris@101: (true_type uses_allocator, OutermostAlloc& outermost_alloc,\ Chris@101: InnerAlloc& inner_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ Chris@101: {\ Chris@101: (void)uses_allocator;\ Chris@101: dispatch_allocator_prefix_suffix\ Chris@101: ( bool_< is_constructible_with_allocator_prefix::value >()\ Chris@101: , outermost_alloc, inner_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ Chris@101: }\ Chris@101: \ Chris@101: template < typename OutermostAlloc, typename InnerAlloc, typename T\ Chris@101: BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\ Chris@101: inline void dispatch_uses_allocator\ Chris@101: (false_type uses_allocator, OutermostAlloc &outermost_alloc,\ Chris@101: InnerAlloc &inner_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ Chris@101: {\ Chris@101: (void)uses_allocator; (void)inner_alloc;\ Chris@101: allocator_traits::construct(outermost_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ Chris@101: }\ Chris@101: // Chris@101: BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE) Chris@101: #undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE Chris@16: Chris@16: #endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@16: #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@16: template Chris@16: class scoped_allocator_adaptor_base Chris@16: : public OuterAlloc Chris@16: { Chris@16: typedef allocator_traits outer_traits_type; Chris@16: BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base) Chris@16: Chris@16: public: Chris@16: template Chris@16: struct rebind_base Chris@16: { Chris@16: typedef scoped_allocator_adaptor_base other; Chris@16: }; Chris@16: Chris@16: typedef OuterAlloc outer_allocator_type; Chris@16: typedef scoped_allocator_adaptor inner_allocator_type; Chris@16: typedef allocator_traits inner_traits_type; Chris@16: typedef scoped_allocator_adaptor Chris@16: scoped_allocator_type; Chris@101: typedef container_detail::bool_< Chris@16: outer_traits_type::propagate_on_container_copy_assignment::value || Chris@16: inner_allocator_type::propagate_on_container_copy_assignment::value Chris@16: > propagate_on_container_copy_assignment; Chris@101: typedef container_detail::bool_< Chris@16: outer_traits_type::propagate_on_container_move_assignment::value || Chris@16: inner_allocator_type::propagate_on_container_move_assignment::value Chris@16: > propagate_on_container_move_assignment; Chris@101: typedef container_detail::bool_< Chris@16: outer_traits_type::propagate_on_container_swap::value || Chris@16: inner_allocator_type::propagate_on_container_swap::value Chris@16: > propagate_on_container_swap; Chris@101: typedef container_detail::bool_< Chris@101: outer_traits_type::is_always_equal::value && Chris@101: inner_allocator_type::is_always_equal::value Chris@101: > is_always_equal; Chris@16: Chris@16: scoped_allocator_adaptor_base() Chris@16: {} Chris@16: Chris@16: template Chris@16: scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc, const InnerAllocs &...args) Chris@16: : outer_allocator_type(::boost::forward(outerAlloc)) Chris@16: , m_inner(args...) Chris@16: {} Chris@16: Chris@16: scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other) Chris@16: : outer_allocator_type(other.outer_allocator()) Chris@16: , m_inner(other.inner_allocator()) Chris@16: {} Chris@16: Chris@16: scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other) Chris@16: : outer_allocator_type(::boost::move(other.outer_allocator())) Chris@16: , m_inner(::boost::move(other.inner_allocator())) Chris@16: {} Chris@16: Chris@16: template Chris@16: scoped_allocator_adaptor_base Chris@16: (const scoped_allocator_adaptor_base& other) Chris@16: : outer_allocator_type(other.outer_allocator()) Chris@16: , m_inner(other.inner_allocator()) Chris@16: {} Chris@16: Chris@16: template Chris@16: scoped_allocator_adaptor_base Chris@16: (BOOST_RV_REF_BEG scoped_allocator_adaptor_base Chris@16: BOOST_RV_REF_END other) Chris@16: : outer_allocator_type(other.outer_allocator()) Chris@16: , m_inner(other.inner_allocator()) Chris@16: {} Chris@16: Chris@16: public: Chris@16: struct internal_type_t{}; Chris@16: Chris@16: template Chris@16: scoped_allocator_adaptor_base Chris@16: ( internal_type_t Chris@16: , BOOST_FWD_REF(OuterA2) outerAlloc Chris@16: , const inner_allocator_type &inner) Chris@16: : outer_allocator_type(::boost::forward(outerAlloc)) Chris@16: , m_inner(inner) Chris@16: {} Chris@16: Chris@16: public: Chris@16: Chris@16: scoped_allocator_adaptor_base &operator= Chris@16: (BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other) Chris@16: { Chris@16: outer_allocator_type::operator=(other.outer_allocator()); Chris@16: m_inner = other.inner_allocator(); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other) Chris@16: { Chris@16: outer_allocator_type::operator=(boost::move(other.outer_allocator())); Chris@16: m_inner = ::boost::move(other.inner_allocator()); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: void swap(scoped_allocator_adaptor_base &r) Chris@16: { Chris@101: boost::adl_move_swap(this->outer_allocator(), r.outer_allocator()); Chris@101: boost::adl_move_swap(this->m_inner, r.inner_allocator()); Chris@16: } Chris@16: Chris@16: friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r) Chris@16: { l.swap(r); } Chris@16: Chris@101: inner_allocator_type& inner_allocator() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return m_inner; } Chris@16: Chris@101: inner_allocator_type const& inner_allocator() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return m_inner; } Chris@16: Chris@101: outer_allocator_type & outer_allocator() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return static_cast(*this); } Chris@16: Chris@101: const outer_allocator_type &outer_allocator() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return static_cast(*this); } Chris@16: Chris@16: scoped_allocator_type select_on_container_copy_construction() const Chris@16: { Chris@16: return scoped_allocator_type Chris@16: (internal_type_t() Chris@16: ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator()) Chris@16: ,inner_traits_type::select_on_container_copy_construction(this->inner_allocator()) Chris@16: ); Chris@16: } Chris@16: Chris@16: private: Chris@16: inner_allocator_type m_inner; Chris@16: }; Chris@16: Chris@16: #else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@16: //Let's add a dummy first template parameter to allow creating Chris@16: //specializations up to maximum InnerAlloc count Chris@101: template Chris@16: class scoped_allocator_adaptor_base; Chris@16: Chris@16: //Specializations for the adaptor with InnerAlloc allocators Chris@16: Chris@101: #define BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_BASE_CODE(N)\ Chris@101: template \ Chris@101: class scoped_allocator_adaptor_base\ Chris@101: : public OuterAlloc\ Chris@101: {\ Chris@101: typedef allocator_traits outer_traits_type;\ Chris@101: BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base)\ Chris@101: \ Chris@101: public:\ Chris@101: template \ Chris@101: struct rebind_base\ Chris@101: {\ Chris@101: typedef scoped_allocator_adaptor_base other;\ Chris@101: };\ Chris@101: \ Chris@101: typedef OuterAlloc outer_allocator_type;\ Chris@101: typedef scoped_allocator_adaptor inner_allocator_type;\ Chris@101: typedef scoped_allocator_adaptor scoped_allocator_type;\ Chris@101: typedef allocator_traits inner_traits_type;\ Chris@101: typedef container_detail::bool_<\ Chris@101: outer_traits_type::propagate_on_container_copy_assignment::value ||\ Chris@101: inner_allocator_type::propagate_on_container_copy_assignment::value\ Chris@101: > propagate_on_container_copy_assignment;\ Chris@101: typedef container_detail::bool_<\ Chris@101: outer_traits_type::propagate_on_container_move_assignment::value ||\ Chris@101: inner_allocator_type::propagate_on_container_move_assignment::value\ Chris@101: > propagate_on_container_move_assignment;\ Chris@101: typedef container_detail::bool_<\ Chris@101: outer_traits_type::propagate_on_container_swap::value ||\ Chris@101: inner_allocator_type::propagate_on_container_swap::value\ Chris@101: > propagate_on_container_swap;\ Chris@101: \ Chris@101: typedef container_detail::bool_<\ Chris@101: outer_traits_type::is_always_equal::value &&\ Chris@101: inner_allocator_type::is_always_equal::value\ Chris@101: > is_always_equal;\ Chris@101: \ Chris@101: scoped_allocator_adaptor_base(){}\ Chris@101: \ Chris@101: template \ Chris@101: scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc, BOOST_MOVE_CREF##N)\ Chris@101: : outer_allocator_type(::boost::forward(outerAlloc))\ Chris@101: , m_inner(BOOST_MOVE_ARG##N)\ Chris@101: {}\ Chris@101: \ Chris@101: scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)\ Chris@101: : outer_allocator_type(other.outer_allocator())\ Chris@101: , m_inner(other.inner_allocator())\ Chris@101: {}\ Chris@101: \ Chris@101: scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other)\ Chris@101: : outer_allocator_type(::boost::move(other.outer_allocator()))\ Chris@101: , m_inner(::boost::move(other.inner_allocator()))\ Chris@101: {}\ Chris@101: \ Chris@101: template \ Chris@101: scoped_allocator_adaptor_base\ Chris@101: (const scoped_allocator_adaptor_base& other)\ Chris@101: : outer_allocator_type(other.outer_allocator())\ Chris@101: , m_inner(other.inner_allocator())\ Chris@101: {}\ Chris@101: \ Chris@101: template \ Chris@101: scoped_allocator_adaptor_base\ Chris@101: (BOOST_RV_REF_BEG scoped_allocator_adaptor_base BOOST_RV_REF_END other)\ Chris@101: : outer_allocator_type(other.outer_allocator())\ Chris@101: , m_inner(other.inner_allocator())\ Chris@101: {}\ Chris@101: \ Chris@101: public:\ Chris@101: struct internal_type_t{};\ Chris@101: \ Chris@101: template \ Chris@101: scoped_allocator_adaptor_base\ Chris@101: ( internal_type_t, BOOST_FWD_REF(OuterA2) outerAlloc, const inner_allocator_type &inner)\ Chris@101: : outer_allocator_type(::boost::forward(outerAlloc))\ Chris@101: , m_inner(inner)\ Chris@101: {}\ Chris@101: \ Chris@101: public:\ Chris@101: scoped_allocator_adaptor_base &operator=\ Chris@101: (BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other)\ Chris@101: {\ Chris@101: outer_allocator_type::operator=(other.outer_allocator());\ Chris@101: m_inner = other.inner_allocator();\ Chris@101: return *this;\ Chris@101: }\ Chris@101: \ Chris@101: scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other)\ Chris@101: {\ Chris@101: outer_allocator_type::operator=(boost::move(other.outer_allocator()));\ Chris@101: m_inner = ::boost::move(other.inner_allocator());\ Chris@101: return *this;\ Chris@101: }\ Chris@101: \ Chris@101: void swap(scoped_allocator_adaptor_base &r)\ Chris@101: {\ Chris@101: boost::adl_move_swap(this->outer_allocator(), r.outer_allocator());\ Chris@101: boost::adl_move_swap(this->m_inner, r.inner_allocator());\ Chris@101: }\ Chris@101: \ Chris@101: friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)\ Chris@101: { l.swap(r); }\ Chris@101: \ Chris@101: inner_allocator_type& inner_allocator()\ Chris@101: { return m_inner; }\ Chris@101: \ Chris@101: inner_allocator_type const& inner_allocator() const\ Chris@101: { return m_inner; }\ Chris@101: \ Chris@101: outer_allocator_type & outer_allocator()\ Chris@101: { return static_cast(*this); }\ Chris@101: \ Chris@101: const outer_allocator_type &outer_allocator() const\ Chris@101: { return static_cast(*this); }\ Chris@101: \ Chris@101: scoped_allocator_type select_on_container_copy_construction() const\ Chris@101: {\ Chris@101: return scoped_allocator_type\ Chris@101: (internal_type_t()\ Chris@101: ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator())\ Chris@101: ,inner_traits_type::select_on_container_copy_construction(this->inner_allocator())\ Chris@101: );\ Chris@101: }\ Chris@101: private:\ Chris@101: inner_allocator_type m_inner;\ Chris@101: };\ Chris@16: //! Chris@101: BOOST_MOVE_ITERATE_1TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_BASE_CODE) Chris@101: #undef BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_BASE_CODE Chris@16: Chris@16: #endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@101: #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@101: #define BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE ,true Chris@101: #define BOOST_CONTAINER_SCOPEDALLOC_ALLINNER BOOST_MOVE_TARG9 Chris@101: #define BOOST_CONTAINER_SCOPEDALLOC_ALLINNERCLASS BOOST_MOVE_CLASS9 Chris@101: #else Chris@101: #define BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE Chris@101: #define BOOST_CONTAINER_SCOPEDALLOC_ALLINNER InnerAllocs... Chris@101: #define BOOST_CONTAINER_SCOPEDALLOC_ALLINNERCLASS typename... InnerAllocs Chris@101: #endif Chris@101: Chris@16: //Specialization for adaptor without any InnerAlloc Chris@16: template Chris@101: class scoped_allocator_adaptor_base< OuterAlloc BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE> Chris@16: : public OuterAlloc Chris@16: { Chris@16: BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base) Chris@16: public: Chris@16: Chris@16: template Chris@16: struct rebind_base Chris@16: { Chris@16: typedef scoped_allocator_adaptor_base Chris@16: ::template portable_rebind_alloc::type Chris@101: BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE > other; Chris@16: }; Chris@16: Chris@16: typedef OuterAlloc outer_allocator_type; Chris@16: typedef allocator_traits outer_traits_type; Chris@16: typedef scoped_allocator_adaptor inner_allocator_type; Chris@16: typedef inner_allocator_type scoped_allocator_type; Chris@16: typedef allocator_traits inner_traits_type; Chris@16: typedef typename outer_traits_type:: Chris@16: propagate_on_container_copy_assignment propagate_on_container_copy_assignment; Chris@16: typedef typename outer_traits_type:: Chris@16: propagate_on_container_move_assignment propagate_on_container_move_assignment; Chris@16: typedef typename outer_traits_type:: Chris@16: propagate_on_container_swap propagate_on_container_swap; Chris@101: typedef typename outer_traits_type:: Chris@101: is_always_equal is_always_equal; Chris@16: Chris@16: scoped_allocator_adaptor_base() Chris@16: {} Chris@16: Chris@16: template Chris@16: scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc) Chris@16: : outer_allocator_type(::boost::forward(outerAlloc)) Chris@16: {} Chris@16: Chris@16: scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other) Chris@16: : outer_allocator_type(other.outer_allocator()) Chris@16: {} Chris@16: Chris@16: scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other) Chris@16: : outer_allocator_type(::boost::move(other.outer_allocator())) Chris@16: {} Chris@16: Chris@16: template Chris@16: scoped_allocator_adaptor_base Chris@101: (const scoped_allocator_adaptor_base& other) Chris@16: : outer_allocator_type(other.outer_allocator()) Chris@16: {} Chris@16: Chris@16: template Chris@16: scoped_allocator_adaptor_base Chris@101: (BOOST_RV_REF_BEG scoped_allocator_adaptor_base BOOST_RV_REF_END other) Chris@16: : outer_allocator_type(other.outer_allocator()) Chris@16: {} Chris@16: Chris@16: public: Chris@16: struct internal_type_t{}; Chris@16: Chris@16: template Chris@16: scoped_allocator_adaptor_base(internal_type_t, BOOST_FWD_REF(OuterA2) outerAlloc, const inner_allocator_type &) Chris@16: : outer_allocator_type(::boost::forward(outerAlloc)) Chris@16: {} Chris@101: Chris@16: public: Chris@16: scoped_allocator_adaptor_base &operator=(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other) Chris@16: { Chris@16: outer_allocator_type::operator=(other.outer_allocator()); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other) Chris@16: { Chris@16: outer_allocator_type::operator=(boost::move(other.outer_allocator())); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: void swap(scoped_allocator_adaptor_base &r) Chris@16: { Chris@101: boost::adl_move_swap(this->outer_allocator(), r.outer_allocator()); Chris@16: } Chris@16: Chris@16: friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r) Chris@16: { l.swap(r); } Chris@16: Chris@16: inner_allocator_type& inner_allocator() Chris@16: { return static_cast(*this); } Chris@16: Chris@16: inner_allocator_type const& inner_allocator() const Chris@16: { return static_cast(*this); } Chris@16: Chris@16: outer_allocator_type & outer_allocator() Chris@16: { return static_cast(*this); } Chris@16: Chris@16: const outer_allocator_type &outer_allocator() const Chris@16: { return static_cast(*this); } Chris@16: Chris@16: scoped_allocator_type select_on_container_copy_construction() const Chris@16: { Chris@16: return scoped_allocator_type Chris@16: (internal_type_t() Chris@16: ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator()) Chris@16: //Don't use inner_traits_type::select_on_container_copy_construction(this->inner_allocator()) Chris@16: //as inner_allocator() is equal to *this and that would trigger an infinite loop Chris@16: , this->inner_allocator() Chris@16: ); Chris@16: } Chris@16: }; Chris@16: Chris@16: } //namespace container_detail { Chris@16: Chris@101: #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: Chris@16: //Scoped allocator Chris@16: #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: Chris@101: #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST) Chris@16: Chris@101: //! This class is a C++03-compatible implementation of std::scoped_allocator_adaptor. Chris@101: //! The class template scoped_allocator_adaptor is an allocator template that specifies Chris@101: //! the memory resource (the outer allocator) to be used by a container (as any other Chris@101: //! allocator does) and also specifies an inner allocator resource to be passed to Chris@101: //! the constructor of every element within the container. Chris@101: //! Chris@101: //! This adaptor is Chris@101: //! instantiated with one outer and zero or more inner allocator types. If Chris@101: //! instantiated with only one allocator type, the inner allocator becomes the Chris@101: //! scoped_allocator_adaptor itself, thus using the same allocator resource for the Chris@101: //! container and every element within the container and, if the elements themselves Chris@101: //! are containers, each of their elements recursively. If instantiated with more than Chris@101: //! one allocator, the first allocator is the outer allocator for use by the container, Chris@101: //! the second allocator is passed to the constructors of the container's elements, Chris@101: //! and, if the elements themselves are containers, the third allocator is passed to Chris@101: //! the elements' elements, and so on. If containers are nested to a depth greater Chris@101: //! than the number of allocators, the last allocator is used repeatedly, as in the Chris@101: //! single-allocator case, for any remaining recursions. Chris@101: //! Chris@101: //! [Note: The Chris@101: //! scoped_allocator_adaptor is derived from the outer allocator type so it can be Chris@101: //! substituted for the outer allocator type in most expressions. -end note] Chris@101: //! Chris@101: //! In the construct member functions, OUTERMOST(x) is x if x does not have Chris@101: //! an outer_allocator() member function and Chris@101: //! OUTERMOST(x.outer_allocator()) otherwise; OUTERMOST_ALLOC_TRAITS(x) is Chris@101: //! allocator_traits. Chris@101: //! Chris@101: //! [Note: OUTERMOST(x) and Chris@101: //! OUTERMOST_ALLOC_TRAITS(x) are recursive operations. It is incumbent upon Chris@101: //! the definition of outer_allocator() to ensure that the recursion terminates. Chris@101: //! It will terminate for all instantiations of scoped_allocator_adaptor. -end note] Chris@101: template Chris@101: class scoped_allocator_adaptor Chris@16: Chris@101: #else // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST) Chris@16: Chris@101: template Chris@101: class scoped_allocator_adaptor Chris@16: Chris@101: #endif // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST) Chris@16: Chris@16: #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: Chris@101: template Chris@16: class scoped_allocator_adaptor Chris@16: #endif Chris@101: Chris@16: : public container_detail::scoped_allocator_adaptor_base Chris@101: Chris@16: { Chris@16: BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor) Chris@16: Chris@16: public: Chris@101: #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: typedef container_detail::scoped_allocator_adaptor_base Chris@101: base_type; Chris@16: typedef typename base_type::internal_type_t internal_type_t; Chris@101: #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: typedef OuterAlloc outer_allocator_type; Chris@16: //! Type: For exposition only Chris@16: //! Chris@16: typedef allocator_traits outer_traits_type; Chris@101: //! Type: scoped_allocator_adaptor if sizeof...(InnerAllocs) is zero; otherwise, Chris@101: //! scoped_allocator_adaptor. Chris@16: typedef typename base_type::inner_allocator_type inner_allocator_type; Chris@16: typedef allocator_traits inner_traits_type; Chris@16: typedef typename outer_traits_type::value_type value_type; Chris@16: typedef typename outer_traits_type::size_type size_type; Chris@16: typedef typename outer_traits_type::difference_type difference_type; Chris@16: typedef typename outer_traits_type::pointer pointer; Chris@16: typedef typename outer_traits_type::const_pointer const_pointer; Chris@16: typedef typename outer_traits_type::void_pointer void_pointer; Chris@16: typedef typename outer_traits_type::const_void_pointer const_void_pointer; Chris@101: //! Type: A type with a constant boolean value == true if Chris@101: //!`allocator_traits::propagate_on_container_copy_assignment::value` is Chris@101: //! true for any Allocator in the set of OuterAlloc and InnerAllocs..., false otherwise. Chris@16: typedef typename base_type:: Chris@16: propagate_on_container_copy_assignment propagate_on_container_copy_assignment; Chris@101: //! Type: A type with a constant boolean value == true if Chris@101: //!`allocator_traits::propagate_on_container_move_assignment::value` is Chris@101: //! true for any Allocator in the set of OuterAlloc and InnerAllocs..., false otherwise. Chris@16: typedef typename base_type:: Chris@16: propagate_on_container_move_assignment propagate_on_container_move_assignment; Chris@101: Chris@101: //! Type: A type with a constant boolean value == true if Chris@101: //! `allocator_traits::propagate_on_container_swap::value` is Chris@101: //! true for any Allocator in the set of OuterAlloc and InnerAllocs..., false otherwise. Chris@16: typedef typename base_type:: Chris@16: propagate_on_container_swap propagate_on_container_swap; Chris@16: Chris@101: //! Type: A type with a constant boolean value == true if Chris@101: //!`allocator_traits::is_always_equal::value` is Chris@101: //! true for all Allocator in the set of OuterAlloc and InnerAllocs..., false otherwise. Chris@101: typedef typename base_type:: Chris@101: is_always_equal is_always_equal; Chris@101: Chris@16: //! Type: Rebinds scoped allocator to Chris@101: //! typedef scoped_allocator_adaptor Chris@16: //! < typename outer_traits_type::template portable_rebind_alloc::type Chris@101: //! , InnerAllocs... > Chris@16: template Chris@16: struct rebind Chris@16: { Chris@16: typedef scoped_allocator_adaptor Chris@16: < typename outer_traits_type::template portable_rebind_alloc::type Chris@101: , BOOST_CONTAINER_SCOPEDALLOC_ALLINNER> other; Chris@16: }; Chris@16: Chris@16: //! Effects: value-initializes the OuterAlloc base class Chris@16: //! and the inner allocator object. Chris@16: scoped_allocator_adaptor() Chris@16: {} Chris@16: Chris@16: ~scoped_allocator_adaptor() Chris@16: {} Chris@16: Chris@16: //! Effects: initializes each allocator within the adaptor with Chris@16: //! the corresponding allocator from other. Chris@16: scoped_allocator_adaptor(const scoped_allocator_adaptor& other) Chris@16: : base_type(other.base()) Chris@16: {} Chris@16: Chris@16: //! Effects: move constructs each allocator within the adaptor with Chris@16: //! the corresponding allocator from other. Chris@16: scoped_allocator_adaptor(BOOST_RV_REF(scoped_allocator_adaptor) other) Chris@16: : base_type(::boost::move(other.base())) Chris@16: {} Chris@16: Chris@16: #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: Chris@16: //! Requires: OuterAlloc shall be constructible from OuterA2. Chris@16: //! Chris@16: //! Effects: initializes the OuterAlloc base class with boost::forward(outerAlloc) and inner Chris@16: //! with innerAllocs...(hence recursively initializing each allocator within the adaptor with the Chris@16: //! corresponding allocator from the argument list). Chris@16: template Chris@16: scoped_allocator_adaptor(BOOST_FWD_REF(OuterA2) outerAlloc, const InnerAllocs & ...innerAllocs) Chris@16: : base_type(::boost::forward(outerAlloc), innerAllocs...) Chris@16: {} Chris@16: #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: Chris@101: #define BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_RELATED_ALLOCATOR_CONSTRUCTOR_CODE(N)\ Chris@101: template \ Chris@101: scoped_allocator_adaptor(BOOST_FWD_REF(OuterA2) outerAlloc BOOST_MOVE_I##N BOOST_MOVE_CREF##N)\ Chris@101: : base_type(::boost::forward(outerAlloc) BOOST_MOVE_I##N BOOST_MOVE_ARG##N)\ Chris@101: {}\ Chris@101: // Chris@101: BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_RELATED_ALLOCATOR_CONSTRUCTOR_CODE) Chris@101: #undef BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_RELATED_ALLOCATOR_CONSTRUCTOR_CODE Chris@16: Chris@16: #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: Chris@16: //! Requires: OuterAlloc shall be constructible from OuterA2. Chris@16: //! Chris@16: //! Effects: initializes each allocator within the adaptor with the corresponding allocator from other. Chris@16: template Chris@101: scoped_allocator_adaptor(const scoped_allocator_adaptor &other) Chris@16: : base_type(other.base()) Chris@16: {} Chris@16: Chris@16: //! Requires: OuterAlloc shall be constructible from OuterA2. Chris@16: //! Chris@16: //! Effects: initializes each allocator within the adaptor with the corresponding allocator Chris@16: //! rvalue from other. Chris@16: template Chris@101: scoped_allocator_adaptor(BOOST_RV_REF_BEG scoped_allocator_adaptor Chris@101: BOOST_RV_REF_END other) Chris@16: : base_type(::boost::move(other.base())) Chris@16: {} Chris@16: Chris@16: scoped_allocator_adaptor &operator=(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor) other) Chris@16: { return static_cast(base_type::operator=(static_cast(other))); } Chris@16: Chris@16: scoped_allocator_adaptor &operator=(BOOST_RV_REF(scoped_allocator_adaptor) other) Chris@101: { return static_cast(base_type::operator=(boost::move(other.base()))); } Chris@16: Chris@16: #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: //! Effects: swaps *this with r. Chris@16: //! Chris@16: void swap(scoped_allocator_adaptor &r); Chris@16: Chris@16: //! Effects: swaps *this with r. Chris@16: //! Chris@16: friend void swap(scoped_allocator_adaptor &l, scoped_allocator_adaptor &r); Chris@16: Chris@16: //! Returns: Chris@101: //! static_cast(*this). Chris@101: outer_allocator_type & outer_allocator() BOOST_NOEXCEPT_OR_NOTHROW; Chris@16: Chris@16: //! Returns: Chris@101: //! static_cast(*this). Chris@101: const outer_allocator_type &outer_allocator() const BOOST_NOEXCEPT_OR_NOTHROW; Chris@16: Chris@16: //! Returns: Chris@101: //! *this if sizeof...(InnerAllocs) is zero; otherwise, inner. Chris@101: inner_allocator_type& inner_allocator() BOOST_NOEXCEPT_OR_NOTHROW; Chris@16: Chris@16: //! Returns: Chris@101: //! *this if sizeof...(InnerAllocs) is zero; otherwise, inner. Chris@101: inner_allocator_type const& inner_allocator() const BOOST_NOEXCEPT_OR_NOTHROW; Chris@16: Chris@16: #endif //BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: Chris@16: //! Returns: Chris@101: //! allocator_traits::max_size(outer_allocator()). Chris@101: size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW Chris@101: { return outer_traits_type::max_size(this->outer_allocator()); } Chris@16: Chris@16: //! Effects: Chris@101: //! calls OUTERMOST_ALLOC_TRAITS(*this)::destroy(OUTERMOST(*this), p). Chris@16: template Chris@101: void destroy(T* p) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@16: allocator_traits::type> Chris@16: ::destroy(get_outermost_allocator(this->outer_allocator()), p); Chris@16: } Chris@16: Chris@16: //! Returns: Chris@101: //! allocator_traits::allocate(outer_allocator(), n). Chris@16: pointer allocate(size_type n) Chris@101: { return outer_traits_type::allocate(this->outer_allocator(), n); } Chris@16: Chris@16: //! Returns: Chris@101: //! allocator_traits::allocate(outer_allocator(), n, hint). Chris@16: pointer allocate(size_type n, const_void_pointer hint) Chris@101: { return outer_traits_type::allocate(this->outer_allocator(), n, hint); } Chris@16: Chris@16: //! Effects: Chris@101: //! allocator_traits::deallocate(outer_allocator(), p, n). Chris@16: void deallocate(pointer p, size_type n) Chris@101: { outer_traits_type::deallocate(this->outer_allocator(), p, n); } Chris@16: Chris@16: #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@101: //! Returns: A new scoped_allocator_adaptor object where each allocator Chris@101: //! Allocator in the adaptor is initialized from the result of calling Chris@101: //! allocator_traits::select_on_container_copy_construction() on Chris@16: //! the corresponding allocator in *this. Chris@16: scoped_allocator_adaptor select_on_container_copy_construction() const; Chris@16: #endif //BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: Chris@101: #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: base_type &base() { return *this; } Chris@16: Chris@16: const base_type &base() const { return *this; } Chris@101: #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: Chris@16: #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: Chris@16: //! Effects: Chris@101: //! 1) If uses_allocator::value is false calls Chris@101: //! OUTERMOST_ALLOC_TRAITS(*this)::construct Chris@101: //! (OUTERMOST(*this), p, std::forward(args)...). Chris@16: //! Chris@101: //! 2) Otherwise, if uses_allocator::value is true and Chris@101: //! is_constructible::value is true, calls Chris@101: //! OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST(*this), p, allocator_arg, Chris@101: //! inner_allocator(), std::forward(args)...). Chris@16: //! Chris@101: //! [Note: In compilers without advanced decltype SFINAE support, is_constructible can't Chris@16: //! be implemented so that condition will be replaced by Chris@16: //! constructible_with_allocator_prefix::value. -end note] Chris@16: //! Chris@16: //! 3) Otherwise, if uses_allocator::value is true and Chris@101: //! is_constructible::value is true, calls Chris@101: //! OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST(*this), p, Chris@101: //! std::forward(args)..., inner_allocator()). Chris@16: //! Chris@101: //! [Note: In compilers without advanced decltype SFINAE support, is_constructible can't be Chris@16: //! implemented so that condition will be replaced by Chris@101: //! constructible_with_allocator_suffix::value. -end note] Chris@16: //! Chris@16: //! 4) Otherwise, the program is ill-formed. Chris@16: //! Chris@101: //! [Note: An error will result if uses_allocator evaluates Chris@16: //! to true but the specific constructor does not take an allocator. This definition prevents a silent Chris@16: //! failure to pass an inner allocator to a contained element. -end note] Chris@16: template < typename T, class ...Args> Chris@16: #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: void Chris@16: #else Chris@16: typename container_detail::enable_if_c::value, void>::type Chris@16: #endif Chris@16: construct(T* p, BOOST_FWD_REF(Args)...args) Chris@16: { Chris@16: container_detail::dispatch_uses_allocator Chris@101: ( container_detail::bool_::value>() Chris@16: , get_outermost_allocator(this->outer_allocator()) Chris@16: , this->inner_allocator() Chris@16: , p, ::boost::forward(args)...); Chris@16: } Chris@16: Chris@16: #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: Chris@16: //Disable this overload if the first argument is pair as some compilers have Chris@16: //overload selection problems when the first parameter is a pair. Chris@101: #define BOOST_CONTAINER_SCOPED_ALLOCATOR_CONSTRUCT_CODE(N) \ Chris@101: template < typename T BOOST_MOVE_I##N BOOST_MOVE_CLASSQ##N >\ Chris@101: typename container_detail::enable_if_c::value, void>::type\ Chris@101: construct(T* p BOOST_MOVE_I##N BOOST_MOVE_UREFQ##N)\ Chris@101: {\ Chris@101: container_detail::dispatch_uses_allocator\ Chris@101: ( container_detail::bool_::value>()\ Chris@101: , get_outermost_allocator(this->outer_allocator())\ Chris@101: , this->inner_allocator(), p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\ Chris@101: }\ Chris@101: // Chris@101: BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_CONSTRUCT_CODE) Chris@101: #undef BOOST_CONTAINER_SCOPED_ALLOCATOR_CONSTRUCT_CODE Chris@16: Chris@16: #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: Chris@16: template Chris@16: void construct(std::pair* p) Chris@16: { this->construct_pair(p); } Chris@16: Chris@16: template Chris@16: void construct(container_detail::pair* p) Chris@16: { this->construct_pair(p); } Chris@16: Chris@16: template Chris@16: void construct(std::pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y) Chris@16: { this->construct_pair(p, ::boost::forward(x), ::boost::forward(y)); } Chris@16: Chris@16: template Chris@16: void construct(container_detail::pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y) Chris@16: { this->construct_pair(p, ::boost::forward(x), ::boost::forward(y)); } Chris@101: Chris@16: template Chris@16: void construct(std::pair* p, const std::pair& x) Chris@16: { this->construct_pair(p, x); } Chris@16: Chris@16: template Chris@16: void construct( container_detail::pair* p Chris@16: , const container_detail::pair& x) Chris@16: { this->construct_pair(p, x); } Chris@101: Chris@16: template Chris@16: void construct( std::pair* p Chris@16: , BOOST_RV_REF_BEG std::pair BOOST_RV_REF_END x) Chris@16: { this->construct_pair(p, x); } Chris@16: Chris@16: template Chris@16: void construct( container_detail::pair* p Chris@16: , BOOST_RV_REF_BEG container_detail::pair BOOST_RV_REF_END x) Chris@16: { this->construct_pair(p, x); } Chris@16: Chris@101: #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: private: Chris@16: template Chris@16: void construct_pair(Pair* p) Chris@16: { Chris@16: this->construct(container_detail::addressof(p->first)); Chris@16: BOOST_TRY{ Chris@16: this->construct(container_detail::addressof(p->second)); Chris@16: } Chris@16: BOOST_CATCH(...){ Chris@16: this->destroy(container_detail::addressof(p->first)); Chris@16: BOOST_RETHROW Chris@16: } Chris@16: BOOST_CATCH_END Chris@16: } Chris@16: Chris@16: template Chris@16: void construct_pair(Pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y) Chris@16: { Chris@16: this->construct(container_detail::addressof(p->first), ::boost::forward(x)); Chris@16: BOOST_TRY{ Chris@16: this->construct(container_detail::addressof(p->second), ::boost::forward(y)); Chris@16: } Chris@16: BOOST_CATCH(...){ Chris@16: this->destroy(container_detail::addressof(p->first)); Chris@16: BOOST_RETHROW Chris@16: } Chris@16: BOOST_CATCH_END Chris@16: } Chris@16: Chris@16: template Chris@16: void construct_pair(Pair* p, const Pair2& pr) Chris@101: { this->construct_pair(p, pr.first, pr.second); } Chris@16: Chris@16: template Chris@16: void construct_pair(Pair* p, BOOST_RV_REF(Pair2) pr) Chris@101: { this->construct_pair(p, ::boost::move(pr.first), ::boost::move(pr.second)); } Chris@16: Chris@16: //template Chris@16: //void construct(pair* p, piecewise_construct_t, tuple x, tuple y); Chris@16: Chris@16: public: Chris@16: //Internal function Chris@16: template Chris@16: scoped_allocator_adaptor(internal_type_t, BOOST_FWD_REF(OuterA2) outer, const inner_allocator_type& inner) Chris@16: : base_type(internal_type_t(), ::boost::forward(outer), inner) Chris@16: {} Chris@16: Chris@101: #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: }; Chris@16: Chris@101: template Chris@101: inline bool operator==(const scoped_allocator_adaptor& a Chris@101: ,const scoped_allocator_adaptor& b) Chris@101: { Chris@16: #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: const bool has_zero_inner = sizeof...(InnerAllocs) == 0u; Chris@16: #else Chris@101: const bool has_zero_inner = boost::container::container_detail::is_same::value; Chris@16: #endif Chris@101: typedef typename scoped_allocator_adaptor Chris@101: ::outer_allocator_type outer_allocator_type; Chris@101: typedef typename scoped_allocator_adaptor Chris@101: ::inner_allocator_type inner_allocator_type; Chris@101: Chris@101: return allocator_traits::equal(a.outer_allocator(), b.outer_allocator()) Chris@101: && (has_zero_inner || Chris@101: allocator_traits::equal(a.inner_allocator(), b.inner_allocator())); Chris@16: } Chris@16: Chris@101: template Chris@101: inline bool operator!=(const scoped_allocator_adaptor& a Chris@101: ,const scoped_allocator_adaptor& b) Chris@101: { return !(a == b); } Chris@16: Chris@16: }} // namespace boost { namespace container { Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP