From 82fefee743bcb2449d011a5bb9384282d36177cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 22 Mar 2012 18:48:57 +0000 Subject: [PATCH] Experimental scoped_allocator support [SVN r77481] --- doc/Jamfile.v2 | 4 +- doc/container.qbk | 12 +- example/doc_emplace.cpp | 2 +- example/doc_move_containers.cpp | 2 +- example/doc_recursive_containers.cpp | 2 +- example/doc_type_erasure.cpp | 2 +- index.html | 2 +- proj/to-do.txt | 17 +- proj/vc7ide/container.sln | 8 + proj/vc7ide/container.vcproj | 22 +- proj/vc7ide/scoped_allocator_adaptor.vcproj | 139 ++ test/allocator_traits_test.cpp | 4 +- test/deque_test.cpp | 2 +- test/dummy_test_allocator.hpp | 6 +- test/expand_bwd_test_allocator.hpp | 6 +- test/flat_tree_test.cpp | 8 +- test/heap_allocator_v1.hpp | 2 +- test/list_test.cpp | 2 +- test/pair_test.cpp | 2 +- test/print_container.hpp | 2 +- test/scoped_allocator_adaptor_test.cpp | 1404 +++++++++++++++++++ test/set_test.hpp | 2 +- test/slist_test.cpp | 2 +- test/stable_vector_test.cpp | 2 +- test/string_test.cpp | 2 +- test/tree_test.cpp | 4 +- test/util.hpp | 2 +- test/vector_test.cpp | 25 +- test/vector_test.hpp | 2 +- 29 files changed, 1628 insertions(+), 63 deletions(-) create mode 100644 proj/vc7ide/scoped_allocator_adaptor.vcproj create mode 100644 test/scoped_allocator_adaptor_test.cpp diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 4ddc031..8e4eb2b 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -1,6 +1,6 @@ # Boost.Container library documentation Jamfile --------------------------------- # -# Copyright Ion Gaztanaga 2009-2011. Use, modification and +# Copyright Ion Gaztanaga 2009-2012. Use, modification and # distribution is subject to 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) @@ -27,6 +27,8 @@ doxygen autodoc "PREDEFINED=\"insert_const_ref_type= const T&\" \\ \"BOOST_CONTAINER_DOXYGEN_INVOKED\" \\ \"BOOST_RV_REF(T)=T &&\" \\ + \"BOOST_RV_REF_BEG=\" \\ + \"BOOST_RV_REF_END=&&\" \\ \"BOOST_COPY_ASSIGN_REF(T)=const T &\" \\ \"BOOST_RV_REF_2_TEMPL_ARGS(T,a,b)=T &&\" \\ \"BOOST_RV_REF_3_TEMPL_ARGS(T,a,b,c)=TT &&\" \\ diff --git a/doc/container.qbk b/doc/container.qbk index 13d34ac..464bd04 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2009-2011 Ion Gazta\u00F1aga + / Copyright (c) 2009-2012 Ion Gazta\u00F1aga / / 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) @@ -8,7 +8,7 @@ [library Boost.Container [quickbook 1.5] [authors [Gaztanaga, Ion]] - [copyright 2009-2011 Ion Gaztanaga] + [copyright 2009-2012 Ion Gaztanaga] [id container] [dirname container] [purpose Containers library] @@ -37,9 +37,9 @@ In short, what does [*Boost.Container] offer? (they can be safely placed in shared memory). * The library offers new useful containers: * [classref boost::container::flat_map flat_map], - [classref boost::container::flat_map flat_set], - [classref boost::container::flat_map flat_multiset] and - [classref boost::container::flat_map flat_multiset]: drop-in + [classref boost::container::flat_set flat_set], + [classref boost::container::flat_multiset flat_multiset] and + [classref boost::container::flat_multiset flat_multiset]: drop-in replacements for standard associative containers but more memory friendly and with faster searches. * [classref boost::container::stable_vector stable_vector]: a std::list and std::vector hybrid @@ -378,7 +378,7 @@ adequate for your needs, and that you often need to use insert and erase in the should probably use list instead of slist.]] [*Boost.Container] updates the classic `slist` container with C++11 features like move semantics and placement -insertion and implements it a bit differently for the standard C++11 `forward_list`. `forward_list` has no `size()` +insertion and implements it a bit differently than the standard C++ `forward_list`. `forward_list` has no `size()` method, so it's been designed to allow (or in practice, encourage) implementations without tracking list size with every insertion/erasure, allowing constant-time `splice_after(iterator, forward_list &, iterator, iterator)`-based list merging. On the other hand `slist` offers diff --git a/example/doc_emplace.cpp b/example/doc_emplace.cpp index 68e4a66..d494061 100644 --- a/example/doc_emplace.cpp +++ b/example/doc_emplace.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. 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) // diff --git a/example/doc_move_containers.cpp b/example/doc_move_containers.cpp index 02e037c..c0fa618 100644 --- a/example/doc_move_containers.cpp +++ b/example/doc_move_containers.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. 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) // diff --git a/example/doc_recursive_containers.cpp b/example/doc_recursive_containers.cpp index b184d19..e9e67d5 100644 --- a/example/doc_recursive_containers.cpp +++ b/example/doc_recursive_containers.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. 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) // diff --git a/example/doc_type_erasure.cpp b/example/doc_type_erasure.cpp index 04dca80..73c81f1 100644 --- a/example/doc_type_erasure.cpp +++ b/example/doc_type_erasure.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. 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) // diff --git a/index.html b/index.html index ad39f65..1251783 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,5 @@ diff --git a/proj/to-do.txt b/proj/to-do.txt index d82bd8a..1152393 100644 --- a/proj/to-do.txt +++ b/proj/to-do.txt @@ -1,10 +1,10 @@ ->Change "insert" and "push_back"/"push_front" to catch non-const rvalues ->Add an example with stateful allocators ->Add test to check convertible types in push_back/insert +->Add SCARY iterators. Review allocator traits --> Explicit instantiation of simple allocator & std::allocator to detect missing allocator_traits calls -> Avoid any rebind<>::other -> Review select_on_container_copy_xxx -> Review propagate_on_xxx @@ -12,13 +12,13 @@ Review allocator traits -> Default + swap move constructors correct? -> Review container documentation in swap/copy/move regarding allocators -Check all move constructors: swap might not be a valid idiom, allocators must be move constructed, intrusive containers are now movable +Check all move constructors: swap might not be a valid idiom, allocators must be move constructed, +intrusive containers are now movable Add and test: Test different propagation values and with inequal allocators - propagate_on_container_move_assignment select_on_container_copy_construction propagate_on_container_swap @@ -28,19 +28,12 @@ Test move constructors with data values and unequal allocators An allocator should use a smart allocator not constructible from raw pointers to catch missing pointer_traits calls -Review all internal container swap's to check allocator propagation is correct - Add initializer lists Write forward_list -Review all move constructors to test if allocator is move constructed - check move if noexcept conditions in vector, deque and stable_vector -Add new allocator propagation copy constructors +Detect always equal or unequal allocators at compiler time. operator== returns true_type or false_type -Review all destructors (search for "~") to detect placement destruction and replace it with allocator_traits::destroy - -All functions from base classes like vector_base, node_alloc_holder, etc., should be named with underscore or -similar to avoid namespace pollution. \ No newline at end of file +change virtual functions with pointers to avoid template instantiation for every type \ No newline at end of file diff --git a/proj/vc7ide/container.sln b/proj/vc7ide/container.sln index 38cb19d..7bc2ee8 100644 --- a/proj/vc7ide/container.sln +++ b/proj/vc7ide/container.sln @@ -43,6 +43,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "list_test", "list_test.vcpr ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scoped_allocator_adaptor_test", "scoped_allocator_adaptor.vcproj", "{B4E9FB12-7D7C-4461-83A9-5EB2C78E608F}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug @@ -95,6 +99,10 @@ Global {58CCE183-6092-48FE-A4F7-BA0D3A792632}.Debug.Build.0 = Debug|Win32 {58CCE183-6092-48FE-A4F7-BA0D3A792632}.Release.ActiveCfg = Release|Win32 {58CCE183-6092-48FE-A4F7-BA0D3A792632}.Release.Build.0 = Release|Win32 + {B4E9FB12-7D7C-4461-83A9-5EB2C78E608F}.Debug.ActiveCfg = Debug|Win32 + {B4E9FB12-7D7C-4461-83A9-5EB2C78E608F}.Debug.Build.0 = Debug|Win32 + {B4E9FB12-7D7C-4461-83A9-5EB2C78E608F}.Release.ActiveCfg = Release|Win32 + {B4E9FB12-7D7C-4461-83A9-5EB2C78E608F}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/proj/vc7ide/container.vcproj b/proj/vc7ide/container.vcproj index 7588d88..50610a6 100644 --- a/proj/vc7ide/container.vcproj +++ b/proj/vc7ide/container.vcproj @@ -179,6 +179,9 @@ + + @@ -197,6 +200,9 @@ + + @@ -215,19 +221,6 @@ - - - - - - - - @@ -264,6 +257,9 @@ + + diff --git a/proj/vc7ide/scoped_allocator_adaptor.vcproj b/proj/vc7ide/scoped_allocator_adaptor.vcproj new file mode 100644 index 0000000..f38106c --- /dev/null +++ b/proj/vc7ide/scoped_allocator_adaptor.vcproj @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/allocator_traits_test.cpp b/test/allocator_traits_test.cpp index 36e5a9e..65ce8f3 100644 --- a/test/allocator_traits_test.cpp +++ b/test/allocator_traits_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2011-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2011-2012. 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) // @@ -9,7 +9,7 @@ ////////////////////////////////////////////////////////////////////////////// #include #include -#include +#include #include #include #include diff --git a/test/deque_test.cpp b/test/deque_test.cpp index bc8bf9e..7190e0a 100644 --- a/test/deque_test.cpp +++ b/test/deque_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // diff --git a/test/dummy_test_allocator.hpp b/test/dummy_test_allocator.hpp index 719d0ca..394b5a9 100644 --- a/test/dummy_test_allocator.hpp +++ b/test/dummy_test_allocator.hpp @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -112,10 +112,10 @@ class dummy_test_allocator {} pointer address(reference value) - { return pointer(addressof(value)); } + { return pointer(container_detail::addressof(value)); } const_pointer address(const_reference value) const - { return const_pointer(addressof(value)); } + { return const_pointer(container_detail::addressof(value)); } pointer allocate(size_type, cvoid_ptr = 0) { return 0; } diff --git a/test/expand_bwd_test_allocator.hpp b/test/expand_bwd_test_allocator.hpp index 67aea9d..3f499d2 100644 --- a/test/expand_bwd_test_allocator.hpp +++ b/test/expand_bwd_test_allocator.hpp @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -86,10 +86,10 @@ class expand_bwd_test_allocator , m_offset(other.m_offset), m_allocations(0){ } pointer address(reference value) - { return pointer(addressof(value)); } + { return pointer(container_detail::addressof(value)); } const_pointer address(const_reference value) const - { return const_pointer(addressof(value)); } + { return const_pointer(container_detail::addressof(value)); } pointer allocate(size_type , cvoid_ptr hint = 0) { (void)hint; return 0; } diff --git a/test/flat_tree_test.cpp b/test/flat_tree_test.cpp index 4203704..645a124 100644 --- a/test/flat_tree_test.cpp +++ b/test/flat_tree_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -228,17 +228,17 @@ class recursive_flat_multiset { public: recursive_flat_multiset(const recursive_flat_multiset &c) - : id_(c.id_), flat_set_(c.flat_set_) + : id_(c.id_), flat_multiset_(c.flat_multiset_) {} recursive_flat_multiset & operator =(const recursive_flat_multiset &c) { id_ = c.id_; - flat_set_= c.flat_set_; + flat_multiset_= c.flat_multiset_; return *this; } int id_; - flat_multiset flat_set_; + flat_multiset flat_multiset_; friend bool operator< (const recursive_flat_multiset &a, const recursive_flat_multiset &b) { return a.id_ < b.id_; } }; diff --git a/test/heap_allocator_v1.hpp b/test/heap_allocator_v1.hpp index 32b46b5..10437b5 100644 --- a/test/heap_allocator_v1.hpp +++ b/test/heap_allocator_v1.hpp @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // diff --git a/test/list_test.cpp b/test/list_test.cpp index 602f547..b3fe6b2 100644 --- a/test/list_test.cpp +++ b/test/list_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // diff --git a/test/pair_test.cpp b/test/pair_test.cpp index c44b9d5..6b75b01 100644 --- a/test/pair_test.cpp +++ b/test/pair_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2011-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2011-2012. 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) // diff --git a/test/print_container.hpp b/test/print_container.hpp index 9300c3c..f34a9f3 100644 --- a/test/print_container.hpp +++ b/test/print_container.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // diff --git a/test/scoped_allocator_adaptor_test.cpp b/test/scoped_allocator_adaptor_test.cpp new file mode 100644 index 0000000..cecfade --- /dev/null +++ b/test/scoped_allocator_adaptor_test.cpp @@ -0,0 +1,1404 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2012. 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 + +using namespace boost::container; + + +template +class test_allocator +{ + BOOST_COPYABLE_AND_MOVABLE(test_allocator) + public: + + template + struct rebind + { + typedef test_allocator other; + }; + + typedef container_detail::bool_ propagate_on_container_copy_assignment; + typedef container_detail::bool_ propagate_on_container_move_assignment; + typedef container_detail::bool_ propagate_on_container_swap; + typedef T value_type; + + test_allocator() + {} + + test_allocator(const test_allocator&) + {} + + test_allocator(BOOST_RV_REF(test_allocator) ) + {} + + template + test_allocator(BOOST_RV_REF_BEG test_allocator BOOST_RV_REF_END) + {} + + template + test_allocator(const test_allocator &) + {} + + test_allocator & operator=(BOOST_COPY_ASSIGN_REF(test_allocator)) + { return *this; } + + test_allocator & operator=(BOOST_RV_REF(test_allocator)) + { return *this; } + + std::size_t max_size() const + { return std::size_t(Id); } + + 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)); } +}; + +template +bool operator==( const test_allocator& + , const test_allocator&) +{ return true; } + +template +bool operator!=( const test_allocator& + , const test_allocator&) +{ return false; } + + +template +struct tagged_integer +{}; + +struct mark_on_destructor +{ + mark_on_destructor() + : destroyed(false) + {} + + ~mark_on_destructor() + { + destroyed = true; + } + + bool destroyed; +}; + +//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 test_allocator allocator_type; + typedef allocator_type allocator_constructor_type; + struct nat{}; + typedef nat allocator_arg_type; +}; + +template +struct uses_allocator_base +{ + typedef test_allocator allocator_type; + typedef allocator_type allocator_constructor_type; + typedef 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 mark_on_scoped_allocation + : uses_allocator_base +{ + private: + BOOST_COPYABLE_AND_MOVABLE(mark_on_scoped_allocation) + + public: + + typedef uses_allocator_base base_type; + + //0 user argument constructors + mark_on_scoped_allocation() + : construction_type(NotUsesAllocator), value(0) + {} + + explicit mark_on_scoped_allocation + (typename base_type::allocator_constructor_type) + : construction_type(ConstructibleSuffix), value(0) + {} + + explicit mark_on_scoped_allocation + (typename base_type::allocator_arg_type, typename base_type::allocator_constructor_type) + : construction_type(ConstructiblePrefix), value(0) + {} + + //1 user argument constructors + explicit mark_on_scoped_allocation(int i) + : construction_type(NotUsesAllocator), value(i) + {} + + mark_on_scoped_allocation + (int i, typename base_type::allocator_constructor_type) + : construction_type(ConstructibleSuffix), value(i) + {} + + mark_on_scoped_allocation + ( typename base_type::allocator_arg_type + , typename base_type::allocator_constructor_type + , int i) + : construction_type(ConstructiblePrefix), value(i) + {} + + //Copy constructors + mark_on_scoped_allocation(const mark_on_scoped_allocation &other) + : construction_type(NotUsesAllocator), value(other.value) + {} + + mark_on_scoped_allocation( const mark_on_scoped_allocation &other + , typename base_type::allocator_constructor_type) + : construction_type(ConstructibleSuffix), value(other.value) + {} + + mark_on_scoped_allocation( typename base_type::allocator_arg_type + , typename base_type::allocator_constructor_type + , const mark_on_scoped_allocation &other) + : construction_type(ConstructiblePrefix), value(other.value) + {} + + //Move constructors + mark_on_scoped_allocation(BOOST_RV_REF(mark_on_scoped_allocation) other) + : construction_type(NotUsesAllocator), value(other.value) + { other.value = 0; other.construction_type = NotUsesAllocator; } + + mark_on_scoped_allocation( BOOST_RV_REF(mark_on_scoped_allocation) other + , typename base_type::allocator_constructor_type) + : construction_type(ConstructibleSuffix), value(other.value) + { other.value = 0; other.construction_type = ConstructibleSuffix; } + + mark_on_scoped_allocation( typename base_type::allocator_arg_type + , typename base_type::allocator_constructor_type + , BOOST_RV_REF(mark_on_scoped_allocation) 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 + < ::mark_on_scoped_allocation > + : ::boost::true_type +{}; + +template +struct constructible_with_allocator_suffix + < ::mark_on_scoped_allocation > + : ::boost::true_type +{}; + +} //namespace container { +} //namespace boost { + + +int main() +{ + typedef test_allocator, 0> OuterAlloc; + typedef test_allocator, 10> Outer10IdAlloc; + typedef test_allocator, 0> Rebound9OuterAlloc; + typedef test_allocator, 1> InnerAlloc1; + typedef test_allocator, 2> InnerAlloc2; + typedef test_allocator, 11> Inner11IdAlloc1; + typedef test_allocator, 12> Inner12IdAlloc2; + + typedef test_allocator, 0, false> OuterAllocFalsePropagate; + typedef test_allocator, 0, true> OuterAllocTruePropagate; + typedef test_allocator, 1, false> InnerAlloc1FalsePropagate; + typedef test_allocator, 1, true> InnerAlloc1TruePropagate; + typedef test_allocator, 2, false> InnerAlloc2FalsePropagate; + typedef test_allocator, 2, true> InnerAlloc2TruePropagate; + + // + typedef scoped_allocator_adaptor< OuterAlloc > Scoped0Inner; + typedef scoped_allocator_adaptor< OuterAlloc + , InnerAlloc1 > Scoped1Inner; + typedef scoped_allocator_adaptor< OuterAlloc + , InnerAlloc1 + , InnerAlloc2 > Scoped2Inner; + typedef scoped_allocator_adaptor + < scoped_allocator_adaptor + + > ScopedScoped0Inner; + typedef scoped_allocator_adaptor + < scoped_allocator_adaptor + + , InnerAlloc1 + > ScopedScoped1Inner; + typedef scoped_allocator_adaptor + < scoped_allocator_adaptor + + , InnerAlloc1, InnerAlloc2 + > ScopedScoped2Inner; + typedef scoped_allocator_adaptor< Rebound9OuterAlloc > Rebound9Scoped0Inner; + typedef scoped_allocator_adaptor< Rebound9OuterAlloc + , InnerAlloc1 > Rebound9Scoped1Inner; + typedef scoped_allocator_adaptor< Rebound9OuterAlloc + , InnerAlloc1 + , InnerAlloc2 > Rebound9Scoped2Inner; + + //outer_allocator_type + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< OuterAlloc + , Scoped0Inner::outer_allocator_type>::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< OuterAlloc + , Scoped1Inner::outer_allocator_type>::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< OuterAlloc + , Scoped2Inner::outer_allocator_type>::value )); + //value_type + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::value_type + , Scoped0Inner::value_type>::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::value_type + , Scoped1Inner::value_type>::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::value_type + , Scoped2Inner::value_type>::value )); + //size_type + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::size_type + , Scoped0Inner::size_type>::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::size_type + , Scoped1Inner::size_type>::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::size_type + , Scoped2Inner::size_type>::value )); + + //difference_type + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::difference_type + , Scoped0Inner::difference_type>::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::difference_type + , Scoped1Inner::difference_type>::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::difference_type + , Scoped2Inner::difference_type>::value )); + + //pointer + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::pointer + , Scoped0Inner::pointer>::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::pointer + , Scoped1Inner::pointer>::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::pointer + , Scoped2Inner::pointer>::value )); + + //const_pointer + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::const_pointer + , Scoped0Inner::const_pointer>::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::const_pointer + , Scoped1Inner::const_pointer>::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::const_pointer + , Scoped2Inner::const_pointer>::value )); + + //void_pointer + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::void_pointer + , Scoped0Inner::void_pointer>::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::void_pointer + , Scoped1Inner::void_pointer>::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::void_pointer + , Scoped2Inner::void_pointer>::value )); + + //const_void_pointer + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::const_void_pointer + , Scoped0Inner::const_void_pointer>::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::const_void_pointer + , Scoped1Inner::const_void_pointer>::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< allocator_traits::const_void_pointer + , Scoped2Inner::const_void_pointer>::value )); + + //rebind + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same >::other + , Rebound9Scoped0Inner >::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same >::other + , Rebound9Scoped1Inner >::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same >::other + , Rebound9Scoped2Inner >::value )); + + //inner_allocator_type + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< Scoped0Inner + , Scoped0Inner::inner_allocator_type>::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< scoped_allocator_adaptor + , Scoped1Inner::inner_allocator_type>::value )); + BOOST_STATIC_ASSERT(( boost::container::container_detail::is_same< scoped_allocator_adaptor + , Scoped2Inner::inner_allocator_type>::value )); + + { + //Propagation test + typedef scoped_allocator_adaptor< OuterAllocFalsePropagate > Scoped0InnerF; + typedef scoped_allocator_adaptor< OuterAllocTruePropagate > Scoped0InnerT; + typedef scoped_allocator_adaptor< OuterAllocFalsePropagate + , InnerAlloc1FalsePropagate > Scoped1InnerFF; + typedef scoped_allocator_adaptor< OuterAllocFalsePropagate + , InnerAlloc1TruePropagate > Scoped1InnerFT; + typedef scoped_allocator_adaptor< OuterAllocTruePropagate + , InnerAlloc1FalsePropagate > Scoped1InnerTF; + typedef scoped_allocator_adaptor< OuterAllocTruePropagate + , InnerAlloc1TruePropagate > Scoped1InnerTT; + typedef scoped_allocator_adaptor< OuterAllocFalsePropagate + , InnerAlloc1FalsePropagate + , InnerAlloc2FalsePropagate > Scoped2InnerFFF; + typedef scoped_allocator_adaptor< OuterAllocFalsePropagate + , InnerAlloc1FalsePropagate + , InnerAlloc2TruePropagate > Scoped2InnerFFT; + typedef scoped_allocator_adaptor< OuterAllocFalsePropagate + , InnerAlloc1TruePropagate + , InnerAlloc2FalsePropagate > Scoped2InnerFTF; + typedef scoped_allocator_adaptor< OuterAllocFalsePropagate + , InnerAlloc1TruePropagate + , InnerAlloc2TruePropagate > Scoped2InnerFTT; + typedef scoped_allocator_adaptor< OuterAllocTruePropagate + , InnerAlloc1FalsePropagate + , InnerAlloc2FalsePropagate > Scoped2InnerTFF; + typedef scoped_allocator_adaptor< OuterAllocTruePropagate + , InnerAlloc1FalsePropagate + , InnerAlloc2TruePropagate > Scoped2InnerTFT; + typedef scoped_allocator_adaptor< OuterAllocTruePropagate + , InnerAlloc1TruePropagate + , InnerAlloc2FalsePropagate > Scoped2InnerTTF; + typedef scoped_allocator_adaptor< OuterAllocTruePropagate + , InnerAlloc1TruePropagate + , InnerAlloc2TruePropagate > Scoped2InnerTTT; + + //propagate_on_container_copy_assignment + //0 inner + BOOST_STATIC_ASSERT(( !Scoped0InnerF::propagate_on_container_copy_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped0InnerT::propagate_on_container_copy_assignment::value )); + //1 inner + BOOST_STATIC_ASSERT(( !Scoped1InnerFF::propagate_on_container_copy_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped1InnerFT::propagate_on_container_copy_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped1InnerTF::propagate_on_container_copy_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped1InnerTT::propagate_on_container_copy_assignment::value )); + //2 inner + BOOST_STATIC_ASSERT(( !Scoped2InnerFFF::propagate_on_container_copy_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerFFT::propagate_on_container_copy_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerFTF::propagate_on_container_copy_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerFTT::propagate_on_container_copy_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerTFF::propagate_on_container_copy_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerTFT::propagate_on_container_copy_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerTTF::propagate_on_container_copy_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerTTT::propagate_on_container_copy_assignment::value )); + + //propagate_on_container_move_assignment + //0 inner + BOOST_STATIC_ASSERT(( !Scoped0InnerF::propagate_on_container_move_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped0InnerT::propagate_on_container_move_assignment::value )); + //1 inner + BOOST_STATIC_ASSERT(( !Scoped1InnerFF::propagate_on_container_move_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped1InnerFT::propagate_on_container_move_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped1InnerTF::propagate_on_container_move_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped1InnerTT::propagate_on_container_move_assignment::value )); + //2 inner + BOOST_STATIC_ASSERT(( !Scoped2InnerFFF::propagate_on_container_move_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerFFT::propagate_on_container_move_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerFTF::propagate_on_container_move_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerFTT::propagate_on_container_move_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerTFF::propagate_on_container_move_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerTFT::propagate_on_container_move_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerTTF::propagate_on_container_move_assignment::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerTTT::propagate_on_container_move_assignment::value )); + + //propagate_on_container_swap + //0 inner + BOOST_STATIC_ASSERT(( !Scoped0InnerF::propagate_on_container_swap::value )); + BOOST_STATIC_ASSERT(( Scoped0InnerT::propagate_on_container_swap::value )); + //1 inner + BOOST_STATIC_ASSERT(( !Scoped1InnerFF::propagate_on_container_swap::value )); + BOOST_STATIC_ASSERT(( Scoped1InnerFT::propagate_on_container_swap::value )); + BOOST_STATIC_ASSERT(( Scoped1InnerTF::propagate_on_container_swap::value )); + BOOST_STATIC_ASSERT(( Scoped1InnerTT::propagate_on_container_swap::value )); + //2 inner + BOOST_STATIC_ASSERT(( !Scoped2InnerFFF::propagate_on_container_swap::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerFFT::propagate_on_container_swap::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerFTF::propagate_on_container_swap::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerFTT::propagate_on_container_swap::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerTFF::propagate_on_container_swap::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerTFT::propagate_on_container_swap::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerTTF::propagate_on_container_swap::value )); + BOOST_STATIC_ASSERT(( Scoped2InnerTTT::propagate_on_container_swap::value )); + } + + //Default constructor + { + Scoped0Inner s0i; + Scoped1Inner s1i; + } + + //inner_allocator() + { + Scoped0Inner s0i; + Scoped1Inner s1i; + Scoped2Inner s2i; + const Scoped0Inner const_s0i; + const Scoped1Inner const_s1i; + const Scoped2Inner const_s2i; + + Scoped0Inner::inner_allocator_type &s0i_inner = s0i.inner_allocator(); + (void)s0i_inner; + const Scoped0Inner::inner_allocator_type &const_s0i_inner = const_s0i.inner_allocator(); + (void)const_s0i_inner; + Scoped1Inner::inner_allocator_type &s1i_inner = s1i.inner_allocator(); + (void)s1i_inner; + const Scoped1Inner::inner_allocator_type &const_s1i_inner = const_s1i.inner_allocator(); + (void)const_s1i_inner; + Scoped2Inner::inner_allocator_type &s2i_inner = s2i.inner_allocator(); + (void)s2i_inner; + const Scoped2Inner::inner_allocator_type &const_s2i_inner = const_s2i.inner_allocator(); + (void)const_s2i_inner; + } + + //operator==/!= + { + const Scoped0Inner const_s0i; + const Rebound9Scoped0Inner const_rs0i; + if(!(const_s0i == const_s0i) || + !(const_rs0i == const_s0i)){ + return 1; + } + if( const_s0i != const_s0i || + const_s0i != const_rs0i ){ + return 1; + } + + const Scoped1Inner const_s1i; + const Rebound9Scoped1Inner const_rs1i; + if(!(const_s1i == const_s1i) || + !(const_rs1i == const_s1i)){ + return 1; + } + if( const_s1i != const_s1i || + const_s1i != const_rs1i ){ + return 1; + } + const Scoped2Inner const_s2i; + const Rebound9Scoped2Inner const_rs2i; + if(!(const_s2i == const_s2i) || + !(const_s2i == const_rs2i) ){ + return 1; + } + if( const_s2i != const_s2i || + const_s2i != const_rs2i ){ + return 1; + } + } + + //outer_allocator() + { + Scoped0Inner s0i; + Scoped1Inner s1i; + Scoped2Inner s2i; + const Scoped0Inner const_s0i; + const Scoped1Inner const_s1i; + const Scoped2Inner const_s2i; + + Scoped0Inner::outer_allocator_type &s0i_inner = s0i.outer_allocator(); + (void)s0i_inner; + const Scoped0Inner::outer_allocator_type &const_s0i_inner = const_s0i.outer_allocator(); + (void)const_s0i_inner; + Scoped1Inner::outer_allocator_type &s1i_inner = s1i.outer_allocator(); + (void)s1i_inner; + const Scoped1Inner::outer_allocator_type &const_s1i_inner = const_s1i.outer_allocator(); + (void)const_s1i_inner; + Scoped2Inner::outer_allocator_type &s2i_inner = s2i.outer_allocator(); + (void)s2i_inner; + const Scoped2Inner::outer_allocator_type &const_s2i_inner = const_s2i.outer_allocator(); + (void)const_s2i_inner; + } + + //max_size() + { + const Scoped0Inner const_s0i; + const Scoped1Inner const_s1i; + const Scoped2Inner const_s2i; + const OuterAlloc const_oa; + const InnerAlloc1 const_ia1; + const InnerAlloc2 const_ia2; + + if(const_s0i.max_size() != const_oa.max_size()){ + return 1; + } + + if(const_s1i.max_size() != const_oa.max_size()){ + return 1; + } + + if(const_s2i.max_size() != const_oa.max_size()){ + return 1; + } + + if(const_s1i.inner_allocator().max_size() != const_ia1.max_size()){ + return 1; + } + + if(const_s2i.inner_allocator().inner_allocator().max_size() != const_ia2.max_size()){ + return 1; + } + } + //Copy and move operations + { + //Construction + { + Scoped0Inner s0i_a, s0i_b(s0i_a), s0i_c(::boost::move(s0i_b)); + Scoped1Inner s1i_a, s1i_b(s1i_a), s1i_c(::boost::move(s1i_b)); + Scoped2Inner s2i_a, s2i_b(s2i_a), s2i_c(::boost::move(s2i_b)); + } + //Assignment + { + Scoped0Inner s0i_a, s0i_b; + s0i_a = s0i_b; + s0i_a = ::boost::move(s0i_b); + Scoped1Inner s1i_a, s1i_b; + s1i_a = s1i_b; + s1i_a = ::boost::move(s1i_b); + Scoped2Inner s2i_a, s2i_b; + s2i_a = s2i_b; + s2i_a = ::boost::move(s2i_b); + } + + OuterAlloc oa; + InnerAlloc1 ia1; + InnerAlloc2 ia2; + Rebound9OuterAlloc roa; + Rebound9Scoped0Inner rs0i; + Rebound9Scoped1Inner rs1i; + Rebound9Scoped2Inner rs2i; + + //Copy from outer + { + Scoped0Inner s0i(oa); + Scoped1Inner s1i(oa, ia1); + Scoped2Inner s2i(oa, ia1, ia2); + } + //Move from outer + { + Scoped0Inner s0i(::boost::move(oa)); + Scoped1Inner s1i(::boost::move(oa), ia1); + Scoped2Inner s2i(::boost::move(oa), ia1, ia2); + } + //Copy from rebound outer + { + Scoped0Inner s0i(roa); + Scoped1Inner s1i(roa, ia1); + Scoped2Inner s2i(roa, ia1, ia2); + } + //Move from rebound outer + { + Scoped0Inner s0i(::boost::move(roa)); + Scoped1Inner s1i(::boost::move(roa), ia1); + Scoped2Inner s2i(::boost::move(roa), ia1, ia2); + } + //Copy from rebound scoped + { + Scoped0Inner s0i(rs0i); + Scoped1Inner s1i(rs1i); + Scoped2Inner s2i(rs2i); + } + //Move from rebound scoped + { + Scoped0Inner s0i(::boost::move(rs0i)); + Scoped1Inner s1i(::boost::move(rs1i)); + Scoped2Inner s2i(::boost::move(rs2i)); + } + } + + { + vector > > dummy; + dummy.push_back(0); + } + + //destroy() + { + { + Scoped0Inner s0i; + mark_on_destructor mod; + s0i.destroy(&mod); + if(!mod.destroyed){ + return 1; + } + } + + { + Scoped1Inner s1i; + mark_on_destructor mod; + s1i.destroy(&mod); + if(!mod.destroyed){ + return 1; + } + } + { + Scoped2Inner s2i; + mark_on_destructor mod; + s2i.destroy(&mod); + if(!mod.destroyed){ + return 1; + } + } + } + + //construct + { + + BOOST_STATIC_ASSERT(( !boost::container::uses_allocator + < ::mark_on_scoped_allocation + , test_allocator + >::value )); + BOOST_STATIC_ASSERT(( boost::container::uses_allocator + < ::mark_on_scoped_allocation + , test_allocator + >::value )); + BOOST_STATIC_ASSERT(( boost::container::uses_allocator + < ::mark_on_scoped_allocation + , test_allocator + >::value )); + BOOST_STATIC_ASSERT(( boost::container::constructible_with_allocator_prefix + < ::mark_on_scoped_allocation >::value )); + BOOST_STATIC_ASSERT(( boost::container::constructible_with_allocator_suffix + < ::mark_on_scoped_allocation >::value )); + + //////////////////////////////////////////////////////////// + //First check scoped allocator with just OuterAlloc. + //In this case OuterAlloc (test_allocator with tag 0) should be + //used to construct types. + //////////////////////////////////////////////////////////// + { + Scoped0Inner s0i; + //Check construction with 0 user arguments + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + s0i.construct(&dummy); + if(dummy.construction_type != NotUsesAllocator || + dummy.value != 0){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + s0i.construct(&dummy); + if(dummy.construction_type != ConstructibleSuffix || + dummy.value != 0){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + s0i.construct(&dummy); + if(dummy.construction_type != ConstructiblePrefix || + dummy.value != 0){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + + //Check construction with 1 user arguments + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + s0i.construct(&dummy, 1); + if(dummy.construction_type != NotUsesAllocator || + dummy.value != 1){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + s0i.construct(&dummy, 2); + if(dummy.construction_type != ConstructibleSuffix || + dummy.value != 2){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + s0i.construct(&dummy, 3); + if(dummy.construction_type != ConstructiblePrefix || + dummy.value != 3){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + } + //////////////////////////////////////////////////////////// + //Then check scoped allocator with OuterAlloc and InnerAlloc. + //In this case InnerAlloc (test_allocator with tag 1) should be + //used to construct types. + //////////////////////////////////////////////////////////// + { + Scoped1Inner s1i; + //Check construction with 0 user arguments + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + s1i.construct(&dummy); + if(dummy.construction_type != NotUsesAllocator || + dummy.value != 0){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + s1i.construct(&dummy); + if(dummy.construction_type != ConstructibleSuffix || + dummy.value != 0){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + s1i.construct(&dummy); + if(dummy.construction_type != ConstructiblePrefix || + dummy.value != 0){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + + //Check construction with 1 user arguments + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + s1i.construct(&dummy, 1); + if(dummy.construction_type != NotUsesAllocator || + dummy.value != 1){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + s1i.construct(&dummy, 2); + if(dummy.construction_type != ConstructibleSuffix || + dummy.value != 2){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + s1i.construct(&dummy, 3); + if(dummy.construction_type != ConstructiblePrefix || + dummy.value != 3){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + } + + ////////////////////////////////////////////////////////////////////////////////// + //Now test recursive OuterAllocator types (OuterAllocator is an scoped_allocator) + ////////////////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////// + //First check scoped allocator with just OuterAlloc. + //In this case OuterAlloc (test_allocator with tag 0) should be + //used to construct types. + //////////////////////////////////////////////////////////// + { + //Check outer_allocator_type is scoped + BOOST_STATIC_ASSERT(( boost::container::is_scoped_allocator + ::value )); + BOOST_STATIC_ASSERT(( ::boost::container::container_detail::is_same + < boost::container::outermost_allocator::type + , Outer10IdAlloc + >::value )); + BOOST_STATIC_ASSERT(( ::boost::container::container_detail::is_same + < ScopedScoped0Inner::outer_allocator_type + , scoped_allocator_adaptor + >::value )); + BOOST_STATIC_ASSERT(( ::boost::container::container_detail::is_same + < scoped_allocator_adaptor::outer_allocator_type + , Outer10IdAlloc + >::value )); + ScopedScoped0Inner ssro0i; + Outer10IdAlloc & val = boost::container::outermost_allocator::get(ssro0i); + (void)val; + //Check construction with 0 user arguments + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + ssro0i.construct(&dummy); + if(dummy.construction_type != NotUsesAllocator || + dummy.value != 0){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + ssro0i.construct(&dummy); + if(dummy.construction_type != ConstructibleSuffix || + dummy.value != 0){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + ssro0i.construct(&dummy); + if(dummy.construction_type != ConstructiblePrefix || + dummy.value != 0){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + + //Check construction with 1 user arguments + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + ssro0i.construct(&dummy, 1); + if(dummy.construction_type != NotUsesAllocator || + dummy.value != 1){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + ssro0i.construct(&dummy, 2); + if(dummy.construction_type != ConstructibleSuffix || + dummy.value != 2){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + ssro0i.construct(&dummy, 3); + if(dummy.construction_type != ConstructiblePrefix || + dummy.value != 3){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + } + //////////////////////////////////////////////////////////// + //Then check scoped allocator with OuterAlloc and InnerAlloc. + //In this case inner_allocator_type is not convertible to + //::mark_on_scoped_allocation so uses_allocator + //should be false on all tests. + //////////////////////////////////////////////////////////// + { + //Check outer_allocator_type is scoped + BOOST_STATIC_ASSERT(( boost::container::is_scoped_allocator + ::value )); + BOOST_STATIC_ASSERT(( ::boost::container::container_detail::is_same + < boost::container::outermost_allocator::type + , Outer10IdAlloc + >::value )); + BOOST_STATIC_ASSERT(( ::boost::container::container_detail::is_same + < ScopedScoped1Inner::outer_allocator_type + , scoped_allocator_adaptor + >::value )); + BOOST_STATIC_ASSERT(( ::boost::container::container_detail::is_same + < scoped_allocator_adaptor::outer_allocator_type + , Outer10IdAlloc + >::value )); + BOOST_STATIC_ASSERT(( ! + ::boost::container::uses_allocator + < ::mark_on_scoped_allocation + , ScopedScoped1Inner::inner_allocator_type::outer_allocator_type + >::value )); + ScopedScoped1Inner ssro1i; + Outer10IdAlloc & val = boost::container::outermost_allocator::get(ssro1i); + (void)val; + + //Check construction with 0 user arguments + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + ssro1i.construct(&dummy); + if(dummy.construction_type != NotUsesAllocator || + dummy.value != 0){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + ssro1i.construct(&dummy); + if(dummy.construction_type != NotUsesAllocator || + dummy.value != 0){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + ssro1i.construct(&dummy); + if(dummy.construction_type != NotUsesAllocator || + dummy.value != 0){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + + //Check construction with 1 user arguments + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + ssro1i.construct(&dummy, 1); + if(dummy.construction_type != NotUsesAllocator || + dummy.value != 1){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + ssro1i.construct(&dummy, 2); + if(dummy.construction_type != NotUsesAllocator || + dummy.value != 2){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + MarkType dummy; + dummy.~MarkType(); + ssro1i.construct(&dummy, 3); + if(dummy.construction_type != NotUsesAllocator || + dummy.value != 3){ + dummy.~MarkType(); + return 1; + } + dummy.~MarkType(); + } + } + + //////////////////////////////////////////////////////////// + //Now check propagation to pair + //////////////////////////////////////////////////////////// + //First check scoped allocator with just OuterAlloc. + //In this case OuterAlloc (test_allocator with tag 0) should be + //used to construct types. + //////////////////////////////////////////////////////////// + { + using boost::container::container_detail::pair; + typedef test_allocator< pair< tagged_integer<0> + , tagged_integer<0> >, 0> OuterPairAlloc; + typedef test_allocator< pair< tagged_integer<1> + , tagged_integer<1> >, 1> InnerPairAlloc1; + typedef test_allocator< pair< tagged_integer<2> + , tagged_integer<2> >, 2> InnerPairAlloc2; + // + typedef scoped_allocator_adaptor < OuterPairAlloc > ScopedPair0Inner; + typedef scoped_allocator_adaptor < OuterPairAlloc + , InnerPairAlloc1 > ScopedPair1Inner; + typedef scoped_allocator_adaptor < OuterPairAlloc + , InnerPairAlloc1 + , InnerPairAlloc2 > ScopedPair2Inner; + + ScopedPair0Inner s0i; + //Check construction with 0 user arguments + { + typedef ::mark_on_scoped_allocation MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy); + if(dummy.first.construction_type != NotUsesAllocator || + dummy.second.construction_type != NotUsesAllocator || + dummy.first.value != 0 || + dummy.second.value != 0 ){ + dummy.~MarkTypePair(); + return 1; + } + dummy.~MarkTypePair(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy); + if(dummy.first.construction_type != ConstructibleSuffix || + dummy.second.construction_type != ConstructibleSuffix || + dummy.first.value != 0 || + dummy.second.value != 0 ){ + dummy.~MarkTypePair(); + return 1; + } + dummy.~MarkTypePair(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy); + if(dummy.first.construction_type != ConstructiblePrefix || + dummy.second.construction_type != ConstructiblePrefix || + dummy.first.value != 0 || + dummy.second.value != 0 ){ + dummy.~MarkTypePair(); + return 1; + } + dummy.~MarkTypePair(); + } + + //Check construction with 1 user arguments for each pair + { + typedef ::mark_on_scoped_allocation MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, 1, 1); + if(dummy.first.construction_type != NotUsesAllocator || + dummy.second.construction_type != NotUsesAllocator || + dummy.first.value != 1 || + dummy.second.value != 1 ){ + dummy.~MarkTypePair(); + return 1; + } + dummy.~MarkTypePair(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, 1, 1); + if(dummy.first.construction_type != ConstructibleSuffix || + dummy.second.construction_type != ConstructibleSuffix || + dummy.first.value != 1 || + dummy.second.value != 1 ){ + dummy.~MarkTypePair(); + return 1; + } + dummy.~MarkTypePair(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + dummy.~MarkTypePair(); + s0i.construct(&dummy, 2, 2); + if(dummy.first.construction_type != ConstructiblePrefix || + dummy.second.construction_type != ConstructiblePrefix || + dummy.first.value != 2 || + dummy.second.value != 2 ){ + dummy.~MarkTypePair(); + return 1; + } + dummy.~MarkTypePair(); + } + //Check construction with pair copy construction + { + typedef ::mark_on_scoped_allocation MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy, dummy2; + dummy.~MarkTypePair(); + s0i.construct(&dummy, dummy2); + if(dummy.first.construction_type != NotUsesAllocator || + dummy.second.construction_type != NotUsesAllocator || + dummy.first.value != 0 || + dummy.second.value != 0 ){ + dummy.~MarkTypePair(); + return 1; + } + dummy.~MarkTypePair(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy, dummy2(1, 1); + dummy.~MarkTypePair(); + s0i.construct(&dummy, dummy2); + if(dummy.first.construction_type != ConstructibleSuffix || + dummy.second.construction_type != ConstructibleSuffix || + dummy.first.value != 1 || + dummy.second.value != 1 ){ + dummy.~MarkTypePair(); + return 1; + } + dummy.~MarkTypePair(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy, dummy2(2, 2); + dummy.~MarkTypePair(); + s0i.construct(&dummy, dummy2); + if(dummy.first.construction_type != ConstructiblePrefix || + dummy.second.construction_type != ConstructiblePrefix || + dummy.first.value != 2 || + dummy.second.value != 2 ){ + dummy.~MarkTypePair(); + return 1; + } + dummy.~MarkTypePair(); + } + //Check construction with pair move construction + { + typedef ::mark_on_scoped_allocation MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy, dummy2(3, 3); + dummy2.first.construction_type = dummy2.second.construction_type = ConstructibleSuffix; + dummy.~MarkTypePair(); + s0i.construct(&dummy, ::boost::move(dummy2)); + if(dummy.first.construction_type != NotUsesAllocator || + dummy.second.construction_type != NotUsesAllocator || + dummy.first.value != 3 || + dummy.second.value != 3 || + dummy2.first.construction_type != NotUsesAllocator || + dummy2.second.construction_type != NotUsesAllocator || + dummy2.first.value != 0 || + dummy2.second.value != 0 ){ + dummy.~MarkTypePair(); + return 1; + } + dummy.~MarkTypePair(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy, dummy2(1, 1); + dummy.~MarkTypePair(); + s0i.construct(&dummy, ::boost::move(dummy2)); + if(dummy.first.construction_type != ConstructibleSuffix || + dummy.second.construction_type != ConstructibleSuffix || + dummy.first.value != 1 || + dummy.second.value != 1 || + dummy2.first.construction_type != ConstructibleSuffix || + dummy2.second.construction_type != ConstructibleSuffix || + dummy2.first.value != 0 || + dummy2.second.value != 0 ){ + dummy.~MarkTypePair(); + return 1; + } + dummy.~MarkTypePair(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy, dummy2(2, 2); + dummy.~MarkTypePair(); + s0i.construct(&dummy, ::boost::move(dummy2)); + if(dummy.first.construction_type != ConstructiblePrefix || + dummy.second.construction_type != ConstructiblePrefix || + dummy.first.value != 2 || + dummy.second.value != 2 || + dummy2.first.construction_type != ConstructiblePrefix || + dummy2.second.construction_type != ConstructiblePrefix || + dummy2.first.value != 0 || + dummy2.second.value != 0 ){ + dummy2.~MarkTypePair(); + return 1; + } + dummy.~MarkTypePair(); + } + //Check construction with related pair copy construction + { + typedef ::mark_on_scoped_allocation MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + pair dummy2; + dummy.~MarkTypePair(); + s0i.construct(&dummy, dummy2); + if(dummy.first.construction_type != NotUsesAllocator || + dummy.second.construction_type != NotUsesAllocator || + dummy.first.value != 0 || + dummy.second.value != 0 ){ + dummy.~MarkTypePair(); + return 1; + } + dummy.~MarkTypePair(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + pair dummy2(1, 1); + dummy.~MarkTypePair(); + s0i.construct(&dummy, dummy2); + if(dummy.first.construction_type != ConstructibleSuffix || + dummy.second.construction_type != ConstructibleSuffix || + dummy.first.value != 1 || + dummy.second.value != 1 ){ + dummy.~MarkTypePair(); + return 1; + } + dummy.~MarkTypePair(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + pair dummy2(2, 2); + dummy.~MarkTypePair(); + s0i.construct(&dummy, dummy2); + if(dummy.first.construction_type != ConstructiblePrefix || + dummy.second.construction_type != ConstructiblePrefix || + dummy.first.value != 2 || + dummy.second.value != 2 ){ + dummy.~MarkTypePair(); + return 1; + } + dummy.~MarkTypePair(); + } + //Check construction with related pair move construction + { + typedef ::mark_on_scoped_allocation MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + pair dummy2(3, 3); + dummy.~MarkTypePair(); + s0i.construct(&dummy, ::boost::move(dummy2)); + if(dummy.first.construction_type != NotUsesAllocator || + dummy.second.construction_type != NotUsesAllocator || + dummy.first.value != 3 || + dummy.second.value != 3 ){ + dummy.~MarkTypePair(); + return 1; + } + dummy.~MarkTypePair(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + pair dummy2(1, 1); + dummy.~MarkTypePair(); + s0i.construct(&dummy, ::boost::move(dummy2)); + if(dummy.first.construction_type != ConstructibleSuffix || + dummy.second.construction_type != ConstructibleSuffix || + dummy.first.value != 1 || + dummy.second.value != 1 ){ + dummy.~MarkTypePair(); + return 1; + } + dummy.~MarkTypePair(); + } + { + typedef ::mark_on_scoped_allocation MarkType; + typedef pair MarkTypePair; + MarkTypePair dummy; + pair dummy2(2, 2); + dummy.~MarkTypePair(); + s0i.construct(&dummy, ::boost::move(dummy2)); + if(dummy.first.construction_type != ConstructiblePrefix || + dummy.second.construction_type != ConstructiblePrefix || + dummy.first.value != 2 || + dummy.second.value != 2 ){ + dummy.~MarkTypePair(); + return 1; + } + dummy.~MarkTypePair(); + } + } + } + + return 0; +} +#include diff --git a/test/set_test.hpp b/test/set_test.hpp index 5dd6a2a..95dfee0 100644 --- a/test/set_test.hpp +++ b/test/set_test.hpp @@ -1,6 +1,6 @@ //////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // diff --git a/test/slist_test.cpp b/test/slist_test.cpp index fb9f28f..d1c80e3 100644 --- a/test/slist_test.cpp +++ b/test/slist_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // diff --git a/test/stable_vector_test.cpp b/test/stable_vector_test.cpp index edcd404..fe7d9e1 100644 --- a/test/stable_vector_test.cpp +++ b/test/stable_vector_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // diff --git a/test/string_test.cpp b/test/string_test.cpp index 3799d4a..c51e80b 100644 --- a/test/string_test.cpp +++ b/test/string_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // diff --git a/test/tree_test.cpp b/test/tree_test.cpp index 0717cce..dca5a31 100644 --- a/test/tree_test.cpp +++ b/test/tree_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -201,8 +201,10 @@ void test_move() { //Now test move semantics C original; + original.emplace(); C move_ctor(boost::move(original)); C move_assign; + move_assign.emplace(); move_assign = boost::move(move_ctor); move_assign.swap(original); } diff --git a/test/util.hpp b/test/util.hpp index eea3b00..9bfe1af 100644 --- a/test/util.hpp +++ b/test/util.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // diff --git a/test/vector_test.cpp b/test/vector_test.cpp index 3be90ae..6e393be 100644 --- a/test/vector_test.cpp +++ b/test/vector_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -95,6 +95,26 @@ enum Test int main() { + const std::size_t positions_length = 10; + std::size_t positions[positions_length]; + vector vector_int; + vector vector_int2(positions_length); + for(std::size_t i = 0; i != positions_length; ++i){ + positions[i] = 0u; + } + for(std::size_t i = 0, max = vector_int2.size(); i != max; ++i){ + vector_int2[i] = i; + } + + vector_int.insert(vector_int.begin(), 999); + + vector_int.insert_at_ordered_positions(positions, positions_length, vector_int2.end()); + + for(std::size_t i = 0, max = vector_int.size(); i != max; ++i){ + std::cout << vector_int[i] << std::endl; + } + return 0; +/* recursive_vector_test(); { //Now test move semantics @@ -134,7 +154,8 @@ int main() if(!boost::container::test::test_propagate_allocator()) return 1; - + return 0; + */ } #include diff --git a/test/vector_test.hpp b/test/vector_test.hpp index 4b6d7b7..847e9e8 100644 --- a/test/vector_test.hpp +++ b/test/vector_test.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) //