////////////////////////////////////////////////////////////////////////////// // // (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 #include #include template class propagation_test_allocator { BOOST_COPYABLE_AND_MOVABLE(propagation_test_allocator) public: template struct rebind { typedef propagation_test_allocator other; }; typedef boost::container::container_detail::bool_ propagate_on_container_copy_assignment; typedef boost::container::container_detail::bool_ propagate_on_container_move_assignment; typedef boost::container::container_detail::bool_ propagate_on_container_swap; typedef boost::container::container_detail::bool_ 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 propagation_test_allocator(BOOST_RV_REF_BEG propagation_test_allocator BOOST_RV_REF_END) : m_move_contructed(true), m_move_assigned(false) {} template propagation_test_allocator(const propagation_test_allocator &) {} 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(static_cast(p)); } bool m_move_contructed; bool m_move_assigned; }; template bool operator==( const propagation_test_allocator& , const propagation_test_allocator&) { return true; } template bool operator!=( const propagation_test_allocator& , const propagation_test_allocator&) { 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 struct uses_allocator_base; template struct uses_allocator_base { typedef propagation_test_allocator allocator_type; typedef allocator_type allocator_constructor_type; struct nat{}; typedef nat allocator_arg_type; }; template struct uses_allocator_base { typedef propagation_test_allocator allocator_type; typedef allocator_type allocator_constructor_type; typedef boost::container::allocator_arg_t allocator_arg_type; }; template struct uses_allocator_base { struct nat{}; typedef nat allocator_constructor_type; typedef nat allocator_arg_type; }; template struct allocator_argument_tester : uses_allocator_base { private: BOOST_COPYABLE_AND_MOVABLE(allocator_argument_tester) public: typedef uses_allocator_base 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 struct constructible_with_allocator_prefix < ::allocator_argument_tester > { static const bool value = true; }; template struct constructible_with_allocator_suffix < ::allocator_argument_tester > { static const bool value = true; }; } //namespace container { } //namespace boost { #endif //BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP