////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2011-2013. 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. // ////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include template class SimpleAllocator { public: typedef Ty value_type; explicit SimpleAllocator(int value) : m_state(value) {} template SimpleAllocator(const SimpleAllocator &other) : m_state(other.m_state) {} Ty* allocate(std::size_t n) { return m_allocator.allocate(n); } void deallocate(Ty* p, std::size_t n) { m_allocator.deallocate(p, n); } int get_value() const { return m_state; } private: int m_state; std::allocator m_allocator; template friend class SimpleAllocator; friend bool operator == (const SimpleAllocator &, const SimpleAllocator &) { return true; } friend bool operator != (const SimpleAllocator &, const SimpleAllocator &) { return false; } }; class alloc_int { private: // Not copyable BOOST_MOVABLE_BUT_NOT_COPYABLE(alloc_int) public: typedef SimpleAllocator allocator_type; alloc_int(BOOST_RV_REF(alloc_int)other) : m_value(other.m_value), m_allocator(boost::move(other.m_allocator)) { other.m_value = -1; } alloc_int(BOOST_RV_REF(alloc_int)other, const allocator_type &allocator) : m_value(other.m_value), m_allocator(allocator) { other.m_value = -1; } alloc_int(int value, const allocator_type &allocator) : m_value(value), m_allocator(allocator) {} alloc_int & operator=(BOOST_RV_REF(alloc_int)other) { other.m_value = other.m_value; return *this; } int get_allocator_state() const { return m_allocator.get_value(); } int get_value() const { return m_value; } friend bool operator < (const alloc_int &l, const alloc_int &r) { return l.m_value < r.m_value; } friend bool operator == (const alloc_int &l, const alloc_int &r) { return l.m_value == r.m_value; } private: int m_value; allocator_type m_allocator; }; using namespace ::boost::container; //general allocator typedef scoped_allocator_adaptor > AllocIntAllocator; //[multi]map/set typedef std::pair MapNode; typedef scoped_allocator_adaptor > MapAllocator; typedef map, MapAllocator> Map; typedef set, AllocIntAllocator> Set; typedef multimap, MapAllocator> MultiMap; typedef multiset, AllocIntAllocator> MultiSet; //[multi]flat_map/set typedef std::pair FlatMapNode; typedef scoped_allocator_adaptor > FlatMapAllocator; typedef flat_map, FlatMapAllocator> FlatMap; typedef flat_set, AllocIntAllocator> FlatSet; typedef flat_multimap, FlatMapAllocator> FlatMultiMap; typedef flat_multiset, AllocIntAllocator> FlatMultiSet; //vector, deque, list, slist, stable_vector. typedef vector Vector; typedef deque Deque; typedef list List; typedef slist Slist; typedef stable_vector StableVector; typedef small_vector SmallVector; ///////// //is_unique_assoc ///////// template struct is_unique_assoc { static const bool value = false; }; template struct is_unique_assoc< map > { static const bool value = true; }; template struct is_unique_assoc< flat_map > { static const bool value = true; }; template struct is_unique_assoc< set > { static const bool value = true; }; template struct is_unique_assoc< flat_set > { static const bool value = true; }; ///////// //is_map ///////// template struct is_map { static const bool value = false; }; template struct is_map< map > { static const bool value = true; }; template struct is_map< flat_map > { static const bool value = true; }; template struct is_map< multimap > { static const bool value = true; }; template struct is_map< flat_multimap > { static const bool value = true; }; template struct is_set { static const bool value = false; }; template struct is_set< set > { static const bool value = true; }; template struct is_set< flat_set > { static const bool value = true; }; template struct is_set< multiset > { static const bool value = true; }; template struct is_set< flat_multiset > { static const bool value = true; }; ///////// //container_wrapper ///////// //Try to define-allocator_aware requirements template< class Container , bool Assoc = is_set::value || is_map::value , bool UniqueAssoc = is_unique_assoc::value , bool Map = is_map::value > struct container_wrapper_inserter { typedef typename Container::const_iterator const_iterator; typedef typename Container::iterator iterator; template static iterator emplace(Container &c, const_iterator p, const Arg &arg) { return c.emplace(p, arg); } }; template //map struct container_wrapper_inserter { typedef typename Container::const_iterator const_iterator; typedef typename Container::iterator iterator; template static iterator emplace(Container &c, const_iterator, const Arg &arg) { return c.emplace(arg, arg).first; } }; template //set struct container_wrapper_inserter { typedef typename Container::const_iterator const_iterator; typedef typename Container::iterator iterator; template static iterator emplace(Container &c, const_iterator, const Arg &arg) { return c.emplace(arg).first; } }; template //multimap struct container_wrapper_inserter { typedef typename Container::const_iterator const_iterator; typedef typename Container::iterator iterator; template static iterator emplace(Container &c, const_iterator, const Arg &arg) { return c.emplace(arg, arg); } }; //multiset template //multimap struct container_wrapper_inserter { typedef typename Container::const_iterator const_iterator; typedef typename Container::iterator iterator; template static iterator emplace(Container &c, const_iterator, const Arg &arg) { return c.emplace(arg); } }; template< class Container> struct container_wrapper : public Container { private: BOOST_COPYABLE_AND_MOVABLE(container_wrapper) public: typedef typename Container::allocator_type allocator_type; typedef typename Container::const_iterator const_iterator; typedef typename Container::iterator iterator; container_wrapper(const allocator_type &a) : Container(a) {} container_wrapper(BOOST_RV_REF(container_wrapper) o, const allocator_type &a) : Container(BOOST_MOVE_BASE(Container, o), a) {} container_wrapper(const container_wrapper &o, const allocator_type &a) : Container(o, a) {} template iterator emplace(const_iterator p, const Arg &arg) { return container_wrapper_inserter::emplace(*this, p, arg); } }; bool test_value_and_state_equals(const alloc_int &r, int value, int state) { return r.get_value() == value && r.get_allocator_state() == state; } template bool test_value_and_state_equals(const container_detail::pair &p, int value, int state) { return test_value_and_state_equals(p.first, value, state) && test_alloc_state_equals(p.second, value, state); } template bool test_value_and_state_equals(const std::pair &p, int value, int state) { return test_value_and_state_equals(p.first, value, state) && test_value_and_state_equals(p.second, value, state); } template bool one_level_allocator_propagation_test() { typedef container_wrapper ContainerWrapper; typedef typename ContainerWrapper::iterator iterator; typedef typename ContainerWrapper::allocator_type allocator_type; typedef typename ContainerWrapper::value_type value_type; { allocator_type al(SimpleAllocator(5)); ContainerWrapper c(al); c.clear(); iterator it = c.emplace(c.cbegin(), 42); if(!test_value_and_state_equals(*it, 42, 5)) return false; } { allocator_type al(SimpleAllocator(4)); ContainerWrapper c2(al); ContainerWrapper c(::boost::move(c2), allocator_type(SimpleAllocator(5))); c.clear(); iterator it = c.emplace(c.cbegin(), 42); if(!test_value_and_state_equals(*it, 42, 5)) return false; }/* { ContainerWrapper c2(allocator_type(SimpleAllocator(3))); ContainerWrapper c(c2, allocator_type(SimpleAllocator(5))); c.clear(); iterator it = c.emplace(c.cbegin(), 42); if(!test_value_and_state_equals(*it, 42, 5)) return false; }*/ return true; } int main() { //unique assoc if(!one_level_allocator_propagation_test()) return 1; if(!one_level_allocator_propagation_test()) return 1; if(!one_level_allocator_propagation_test()) return 1; if(!one_level_allocator_propagation_test()) return 1; //multi assoc if(!one_level_allocator_propagation_test()) return 1; if(!one_level_allocator_propagation_test()) return 1; if(!one_level_allocator_propagation_test()) return 1; if(!one_level_allocator_propagation_test()) return 1; //sequence containers if(!one_level_allocator_propagation_test()) return 1; if(!one_level_allocator_propagation_test()) return 1; if(!one_level_allocator_propagation_test()) return 1; if(!one_level_allocator_propagation_test()) return 1; if(!one_level_allocator_propagation_test()) return 1; if(!one_level_allocator_propagation_test()) return 1; return 0; } #include