| ////////////////////////////////////////////////////////////////////////////// |
| // |
| // (C) Copyright Ion Gaztanaga 2015-2015. 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_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP |
| #define BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP |
| |
| #include <boost/container/uses_allocator.hpp> |
| #include <boost/container/detail/mpl.hpp> |
| #include <boost/move/core.hpp> |
| |
| template<class T, unsigned int Id, bool HasTrueTypes = false> |
| class propagation_test_allocator |
| { |
| BOOST_COPYABLE_AND_MOVABLE(propagation_test_allocator) |
| public: |
| |
| template<class U> |
| struct rebind |
| { |
| typedef propagation_test_allocator<U, Id, HasTrueTypes> other; |
| }; |
| |
| typedef boost::container::dtl::bool_<HasTrueTypes> propagate_on_container_copy_assignment; |
| typedef boost::container::dtl::bool_<HasTrueTypes> propagate_on_container_move_assignment; |
| typedef boost::container::dtl::bool_<HasTrueTypes> propagate_on_container_swap; |
| typedef boost::container::dtl::bool_<HasTrueTypes> is_always_equal; |
| typedef T value_type; |
| |
| propagation_test_allocator() |
| : m_move_contructed(false), m_move_assigned(false) |
| {} |
| |
| propagation_test_allocator(const propagation_test_allocator&) |
| : m_move_contructed(false), m_move_assigned(false) |
| {} |
| |
| propagation_test_allocator(BOOST_RV_REF(propagation_test_allocator) ) |
| : m_move_contructed(true), m_move_assigned(false) |
| {} |
| |
| template<class U> |
| propagation_test_allocator(BOOST_RV_REF_BEG propagation_test_allocator<U, Id, HasTrueTypes> BOOST_RV_REF_END) |
| : m_move_contructed(true), m_move_assigned(false) |
| {} |
| |
| template<class U> |
| propagation_test_allocator(const propagation_test_allocator<U, Id, HasTrueTypes> &) |
| {} |
| |
| propagation_test_allocator & operator=(BOOST_COPY_ASSIGN_REF(propagation_test_allocator)) |
| { |
| return *this; |
| } |
| |
| propagation_test_allocator & operator=(BOOST_RV_REF(propagation_test_allocator)) |
| { |
| m_move_assigned = true; |
| return *this; |
| } |
| |
| std::size_t max_size() const |
| { return std::size_t(-1); } |
| |
| T* allocate(std::size_t n) |
| { return (T*)::new char[n*sizeof(T)]; } |
| |
| void deallocate(T*p, std::size_t) |
| { delete []static_cast<char*>(static_cast<void*>(p)); } |
| |
| bool m_move_contructed; |
| bool m_move_assigned; |
| }; |
| |
| template <class T1, class T2, unsigned int Id, bool HasTrueTypes> |
| bool operator==( const propagation_test_allocator<T1, Id, HasTrueTypes>& |
| , const propagation_test_allocator<T2, Id, HasTrueTypes>&) |
| { return true; } |
| |
| template <class T1, class T2, unsigned int Id, bool HasTrueTypes> |
| bool operator!=( const propagation_test_allocator<T1, Id, HasTrueTypes>& |
| , const propagation_test_allocator<T2, Id, HasTrueTypes>&) |
| { return false; } |
| |
| //This enum lists the construction options |
| //for an allocator-aware type |
| enum ConstructionTypeEnum |
| { |
| ConstructiblePrefix, |
| ConstructibleSuffix, |
| NotUsesAllocator |
| }; |
| |
| //This base class provices types for |
| //the derived class to implement each construction |
| //type. If a construction type does not apply |
| //the typedef is set to an internal nat |
| //so that the class is not constructible from |
| //the user arguments. |
| template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag> |
| struct uses_allocator_base; |
| |
| template<unsigned int AllocatorTag> |
| struct uses_allocator_base<ConstructibleSuffix, AllocatorTag> |
| { |
| typedef propagation_test_allocator<int, AllocatorTag> allocator_type; |
| typedef allocator_type allocator_constructor_type; |
| struct nat{}; |
| typedef nat allocator_arg_type; |
| }; |
| |
| template<unsigned int AllocatorTag> |
| struct uses_allocator_base<ConstructiblePrefix, AllocatorTag> |
| { |
| typedef propagation_test_allocator<int, AllocatorTag> allocator_type; |
| typedef allocator_type allocator_constructor_type; |
| typedef boost::container::allocator_arg_t allocator_arg_type; |
| }; |
| |
| template<unsigned int AllocatorTag> |
| struct uses_allocator_base<NotUsesAllocator, AllocatorTag> |
| { |
| struct nat{}; |
| typedef nat allocator_constructor_type; |
| typedef nat allocator_arg_type; |
| }; |
| |
| template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag> |
| struct allocator_argument_tester |
| : uses_allocator_base<ConstructionType, AllocatorTag> |
| { |
| private: |
| BOOST_COPYABLE_AND_MOVABLE(allocator_argument_tester) |
| |
| public: |
| |
| typedef uses_allocator_base<ConstructionType, AllocatorTag> base_type; |
| |
| //0 user argument constructors |
| allocator_argument_tester() |
| : construction_type(NotUsesAllocator), value(0) |
| {} |
| |
| explicit allocator_argument_tester |
| (typename base_type::allocator_constructor_type) |
| : construction_type(ConstructibleSuffix), value(0) |
| {} |
| |
| explicit allocator_argument_tester |
| (typename base_type::allocator_arg_type, typename base_type::allocator_constructor_type) |
| : construction_type(ConstructiblePrefix), value(0) |
| {} |
| |
| //1 user argument constructors |
| explicit allocator_argument_tester(int i) |
| : construction_type(NotUsesAllocator), value(i) |
| {} |
| |
| allocator_argument_tester |
| (int i, typename base_type::allocator_constructor_type) |
| : construction_type(ConstructibleSuffix), value(i) |
| {} |
| |
| allocator_argument_tester |
| ( typename base_type::allocator_arg_type |
| , typename base_type::allocator_constructor_type |
| , int i) |
| : construction_type(ConstructiblePrefix), value(i) |
| {} |
| |
| //Copy constructors |
| allocator_argument_tester(const allocator_argument_tester &other) |
| : construction_type(NotUsesAllocator), value(other.value) |
| {} |
| |
| allocator_argument_tester( const allocator_argument_tester &other |
| , typename base_type::allocator_constructor_type) |
| : construction_type(ConstructibleSuffix), value(other.value) |
| {} |
| |
| allocator_argument_tester( typename base_type::allocator_arg_type |
| , typename base_type::allocator_constructor_type |
| , const allocator_argument_tester &other) |
| : construction_type(ConstructiblePrefix), value(other.value) |
| {} |
| |
| //Move constructors |
| allocator_argument_tester(BOOST_RV_REF(allocator_argument_tester) other) |
| : construction_type(NotUsesAllocator), value(other.value) |
| { other.value = 0; other.construction_type = NotUsesAllocator; } |
| |
| allocator_argument_tester( BOOST_RV_REF(allocator_argument_tester) other |
| , typename base_type::allocator_constructor_type) |
| : construction_type(ConstructibleSuffix), value(other.value) |
| { other.value = 0; other.construction_type = ConstructibleSuffix; } |
| |
| allocator_argument_tester( typename base_type::allocator_arg_type |
| , typename base_type::allocator_constructor_type |
| , BOOST_RV_REF(allocator_argument_tester) other) |
| : construction_type(ConstructiblePrefix), value(other.value) |
| { other.value = 0; other.construction_type = ConstructiblePrefix; } |
| |
| ConstructionTypeEnum construction_type; |
| int value; |
| }; |
| |
| namespace boost { |
| namespace container { |
| |
| template<unsigned int AllocatorTag> |
| struct constructible_with_allocator_prefix |
| < ::allocator_argument_tester<ConstructiblePrefix, AllocatorTag> > |
| { |
| static const bool value = true; |
| }; |
| |
| template<unsigned int AllocatorTag> |
| struct constructible_with_allocator_suffix |
| < ::allocator_argument_tester<ConstructibleSuffix, AllocatorTag> > |
| { |
| static const bool value = true; |
| }; |
| |
| } //namespace container { |
| } //namespace boost { |
| |
| #endif //BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP |