/* Boost.MultiIndex test for allocator awareness. * * Copyright 2003-2020 Joaquin M Lopez Munoz. * 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/multi_index for library home page. */ #include "test_alloc_awareness.hpp" #include /* keep it first to prevent nasty warns in MSVC */ #include #include #include #include "pre_multi_index.hpp" #include #include #include #include #include #include #include #include "rooted_allocator.hpp" struct move_tracker { move_tracker(int n):n(n),move_cted(false){} move_tracker(const move_tracker& x):n(x.n),move_cted(false){} move_tracker(BOOST_RV_REF(move_tracker) x):n(x.n),move_cted(true){} move_tracker& operator=(BOOST_COPY_ASSIGN_REF(move_tracker) x) {n=x.n;return *this;} move_tracker& operator=(BOOST_RV_REF(move_tracker) x){n=x.n;return *this;} int n; bool move_cted; private: BOOST_COPYABLE_AND_MOVABLE(move_tracker) }; inline bool operator==(const move_tracker& x,const move_tracker& y) { return x.n==y.n; } inline bool operator<(const move_tracker& x,const move_tracker& y) { return x.n h; return h(x.n); } #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) } /* namespace boost */ #endif #if defined(BOOST_NO_CXX17_IF_CONSTEXPR)&&defined(BOOST_MSVC) #pragma warning(push) #pragma warning(disable:4127) /* conditional expression is constant */ #endif template void test_allocator_awareness_for() { using namespace boost::multi_index; typedef rooted_allocator allocator; typedef multi_index_container< move_tracker, indexed_by< hashed_unique >, ordered_unique >, random_access<>, ranked_unique >, sequenced<> >, allocator > container; allocator root1(0),root2(0); container c(root1); for(int i=0;i<10;++i)c.emplace(i); BOOST_TEST(c.get_allocator().comes_from(root1)); { container c2(c,root2); BOOST_TEST(c2.get_allocator().comes_from(root2)); BOOST_TEST(c2==c); } { container c2(c); const move_tracker* pfirst=&*c2.begin(); container c3(boost::move(c2),root2); BOOST_TEST(c3.get_allocator().comes_from(root2)); BOOST_TEST(c3==c); BOOST_TEST(c2.empty()); BOOST_TEST(AlwaysEqual==(&*c3.begin()==pfirst)); BOOST_TEST(!AlwaysEqual==(c3.begin()->move_cted)); } { container c2(root2); c2=c; BOOST_TEST(c2.get_allocator().comes_from(Propagate?root1:root2)); BOOST_TEST(c2==c); } { const bool element_transfer=Propagate||AlwaysEqual; container c2(c); const move_tracker* pfirst=&*c2.begin(); container c3(root2); c3=boost::move(c2); BOOST_TEST(c3.get_allocator().comes_from(Propagate?root1:root2)); BOOST_TEST(c3==c); BOOST_TEST(c2.empty()); BOOST_TEST(element_transfer==(&*c3.begin()==pfirst)); BOOST_TEST(!element_transfer==(c3.begin()->move_cted)); } if(Propagate||AlwaysEqual){ container c2(c); const move_tracker* pfirst=&*c2.begin(); container c3(root2); c3.swap(c2); BOOST_TEST(c2.get_allocator().comes_from(Propagate?root2:root1)); BOOST_TEST(c3.get_allocator().comes_from(Propagate?root1:root2)); BOOST_TEST(c3==c); BOOST_TEST(c2.empty()); BOOST_TEST(&*c3.begin()==pfirst); BOOST_TEST(!c3.begin()->move_cted); } } #if defined(BOOST_NO_CXX17_IF_CONSTEXPR)&&defined(BOOST_MSVC) #pragma warning(pop) /* C4127 */ #endif void test_allocator_awareness() { test_allocator_awareness_for(); test_allocator_awareness_for(); #if !defined(BOOST_NO_CXX11_ALLOCATOR) /* only in C+11 onwards are allocators potentially expected to propagate */ test_allocator_awareness_for(); test_allocator_awareness_for(); #endif }