diff --git a/doc/container.qbk b/doc/container.qbk index c9db3ae..644f510 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -1332,6 +1332,8 @@ use [*Boost.Container]? There are several reasons for that: * [@https://github.com/boostorg/container/issues/116 GitHub #116: ['"MSVC + boost 1.70 compilation error when windows.h is already included (detail/thread_mutex.hpp)"]]. * [@https://github.com/boostorg/container/issues/117 GitHub #117: ['"flat_map/map::insert_or_assign with hint has wrong return types"]]. * [@https://github.com/boostorg/container/issues/118 GitHub #118: ['"Non-unique inplace_set_difference used in in flat_tree_merge_unique and iterator invalidation in insert_unique"]]. + * [@https://github.com/boostorg/container/issues/122 GitHub #122: ['"Fix has_trivial_destructor_after_move"]]. + * [@https://github.com/boostorg/container/issues/123 GitHub #123: ['"With heterogeneous lookup, `equal_range` can result in a range with length greater than 1"]]. * [classref boost::container::deque deque] can now have options, using [classref boost::container::deque_options deque_options]. The block size/bytes can be be specified. diff --git a/example/doc_custom_small_vector.cpp b/example/doc_custom_small_vector.cpp new file mode 100644 index 0000000..55fe961 --- /dev/null +++ b/example/doc_custom_small_vector.cpp @@ -0,0 +1,47 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2013-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. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_custom_small_vector +#include +#include + +//Make sure assertions are active +#ifdef NDEBUG +#undef NDEBUG +#endif +#include + +int main () +{ + using namespace boost::container; + + //This option specifies the desired alignment for the internal value_type + typedef small_vector_options< inplace_alignment<16u> >::type alignment_16_option_t; + + //Check 16 byte alignment option + small_vector sv; + assert(((std::size_t)sv.data() % 16u) == 0); + + + //This option specifies that a vector will increase its capacity 50% + //each time the previous capacity was exhausted. + typedef small_vector_options< growth_factor >::type growth_50_option_t; + + //Fill the vector until full capacity is reached + small_vector growth_50_vector(10, 0); + const std::size_t old_cap = growth_50_vector.capacity(); + growth_50_vector.resize(old_cap); + + //Now insert an additional item and check the new buffer is 50% bigger + growth_50_vector.push_back(1); + assert(growth_50_vector.capacity() == old_cap*3/2); + + return 0; +} +//] diff --git a/example/doc_custom_static_vector.cpp b/example/doc_custom_static_vector.cpp new file mode 100644 index 0000000..817ec4c --- /dev/null +++ b/example/doc_custom_static_vector.cpp @@ -0,0 +1,39 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2013-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. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_custom_static_vector +#include +#include + +//Make sure assertions are active +#ifdef NDEBUG +#undef NDEBUG +#endif +#include + +int main () +{ + using namespace boost::container; + + //This option specifies the desired alignment for value_type + typedef static_vector_options< inplace_alignment<16u> >::type alignment_16_option_t; + + //Check 16 byte alignment option + static_vector sv; + assert(((std::size_t)sv.data() % 16u) == 0); + + //This static_vector won't throw on overflow, for maximum performance + typedef static_vector_options< throw_on_overflow >::type no_throw_options_t; + + //Create static_vector with no throw on overflow + static_vector sv2; + + return 0; +} +//] diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp index be88845..ae91106 100644 --- a/include/boost/container/deque.hpp +++ b/include/boost/container/deque.hpp @@ -2295,8 +2295,9 @@ namespace boost { template struct has_trivial_destructor_after_move > { - typedef typename ::boost::container::allocator_traits::pointer pointer; - static const bool value = ::boost::has_trivial_destructor_after_move::value && + typedef typename boost::container::deque::allocator_type allocator_type; + typedef typename ::boost::container::allocator_traits::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move::value && ::boost::has_trivial_destructor_after_move::value; }; diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index 4d86f9e..c346360 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -1605,7 +1605,7 @@ class flat_tree const Compare &key_cmp = this->m_data.get_comp(); KeyOfValue key_extract; RanIt lb(this->priv_lower_bound(first, last, k)), ub(lb); - if(lb != last && static_cast(!key_cmp(k, key_extract(*lb)))){ + if(lb != last && !key_cmp(k, key_extract(*lb))){ ++ub; } return std::pair(lb, ub); @@ -1622,11 +1622,11 @@ template struct has_trivial_destructor_after_move > { - typedef typename boost::container::dtl::select_container_type::type container_type; - typedef typename container_type::allocator_type allocator_t; - typedef typename ::boost::container::allocator_traits::pointer pointer; - static const bool value = ::boost::has_trivial_destructor_after_move::value && - ::boost::has_trivial_destructor_after_move::value; + typedef boost::container::dtl::flat_tree flat_tree; + typedef typename flat_tree::container_type container_type; + typedef typename flat_tree::key_compare key_compare; + static const bool value = ::boost::has_trivial_destructor_after_move::value && + ::boost::has_trivial_destructor_after_move::value; }; } //namespace boost { diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index 42e3564..23fbfde 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -1516,8 +1516,9 @@ struct has_trivial_destructor_after_move > { - typedef typename ::boost::container::allocator_traits::pointer pointer; - static const bool value = ::boost::has_trivial_destructor_after_move::value && + typedef typename ::boost::container::dtl::tree::allocator_type allocator_type; + typedef typename ::boost::container::allocator_traits::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move::value && ::boost::has_trivial_destructor_after_move::value && ::boost::has_trivial_destructor_after_move::value; }; diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index 2b52e14..f1d5ed2 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -1353,7 +1353,9 @@ class flat_map //! Complexity: log(size())+count(k) template BOOST_CONTAINER_FORCEINLINE size_type count(const K& x) const - { return static_cast(m_flat_tree.find(x) != m_flat_tree.end()); } + //Don't use find() != end optimization here as transparent comparators with key K might + //return a different range than key_type (which can only return a single element range) + { return m_flat_tree.count(x); } //! Returns: Returns true if there is an element with key //! equivalent to key in the container, otherwise false. @@ -1465,7 +1467,9 @@ class flat_map //! Complexity: Logarithmic. template BOOST_CONTAINER_FORCEINLINE std::pair equal_range(const K& x) - { return dtl::force_copy >(m_flat_tree.lower_bound_range(x)); } + //Don't use lower_bound_range optimization here as transparent comparators with key K might + //return a different range than key_type (which can only return a single element range) + { return dtl::force_copy >(m_flat_tree.equal_range(x)); } //! Requires: This overload is available only if //! key_compare::is_transparent exists. @@ -1475,7 +1479,9 @@ class flat_map //! Complexity: Logarithmic. template BOOST_CONTAINER_FORCEINLINE std::pair equal_range(const K& x) const - { return dtl::force_copy >(m_flat_tree.lower_bound_range(x)); } + //Don't use lower_bound_range optimization here as transparent comparators with key K might + //return a different range than key_type (which can only return a single element range) + { return dtl::force_copy >(m_flat_tree.equal_range(x)); } //! Effects: Extracts the internal sequence container. //! @@ -1651,10 +1657,10 @@ flat_map(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, A template struct has_trivial_destructor_after_move > { - typedef typename ::boost::container::allocator_traits::pointer pointer; - static const bool value = ::boost::has_trivial_destructor_after_move::value && - ::boost::has_trivial_destructor_after_move::value && - ::boost::has_trivial_destructor_after_move::value; + typedef ::boost::container::dtl::pair value_t; + typedef typename ::boost::container::dtl::container_or_allocator_rebind::type alloc_or_cont_t; + typedef ::boost::container::dtl::flat_tree, Compare, alloc_or_cont_t> tree; + static const bool value = ::boost::has_trivial_destructor_after_move::value; }; namespace container { @@ -2961,10 +2967,10 @@ namespace boost { template struct has_trivial_destructor_after_move< boost::container::flat_multimap > { - typedef typename ::boost::container::allocator_traits::pointer pointer; - static const bool value = ::boost::has_trivial_destructor_after_move::value && - ::boost::has_trivial_destructor_after_move::value && - ::boost::has_trivial_destructor_after_move::value; + typedef ::boost::container::dtl::pair value_t; + typedef typename ::boost::container::dtl::container_or_allocator_rebind::type alloc_or_cont_t; + typedef ::boost::container::dtl::flat_tree, Compare, alloc_or_cont_t> tree; + static const bool value = ::boost::has_trivial_destructor_after_move::value; }; } //namespace boost { diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp index 080beb5..7cb1d5c 100644 --- a/include/boost/container/flat_set.hpp +++ b/include/boost/container/flat_set.hpp @@ -925,7 +925,9 @@ class flat_set //! Complexity: log(size())+count(k) template BOOST_CONTAINER_FORCEINLINE size_type count(const K& x) const - { return static_cast(this->tree_t::find(x) != this->tree_t::cend()); } + //Don't use find() != end optimization here as transparent comparators with key K might + //return a different range than key_type (which can only return a single element range) + { return this->tree_t::count(x); } #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -1031,7 +1033,9 @@ class flat_set //! Complexity: Logarithmic template std::pair equal_range(const K& x) - { return this->tree_t::lower_bound_range(x); } + //Don't use lower_bound_range optimization here as transparent comparators with key K might + //return a different range than key_type (which can only return a single element range) + { return this->tree_t::equal_range(x); } //! Requires: This overload is available only if //! key_compare::is_transparent exists. @@ -1041,7 +1045,9 @@ class flat_set //! Complexity: Logarithmic template std::pair equal_range(const K& x) const - { return this->tree_t::lower_bound_range(x); } + //Don't use lower_bound_range optimization here as transparent comparators with key K might + //return a different range than key_type (which can only return a single element range) + { return this->tree_t::equal_range(x); } #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -1192,10 +1198,8 @@ flat_set(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, A template struct has_trivial_destructor_after_move > { - typedef typename ::boost::container::allocator_traits::pointer pointer; - static const bool value = ::boost::has_trivial_destructor_after_move::value && - ::boost::has_trivial_destructor_after_move::value && - ::boost::has_trivial_destructor_after_move::value; + typedef ::boost::container::dtl::flat_tree, Compare, AllocatorOrContainer> tree; + static const bool value = ::boost::has_trivial_destructor_after_move::value; }; namespace container { @@ -1926,10 +1930,8 @@ flat_multiset(ordered_range_t, InputIterator, InputIterator, Compare const&, All template struct has_trivial_destructor_after_move > { - typedef typename ::boost::container::allocator_traits::pointer pointer; - static const bool value = ::boost::has_trivial_destructor_after_move::value && - ::boost::has_trivial_destructor_after_move::value && - ::boost::has_trivial_destructor_after_move::value; + typedef ::boost::container::dtl::flat_tree, Compare, AllocatorOrContainer> tree; + static const bool value = ::boost::has_trivial_destructor_after_move::value; }; namespace container { diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp index a17a906..f9ff663 100644 --- a/include/boost/container/list.hpp +++ b/include/boost/container/list.hpp @@ -1522,8 +1522,9 @@ list(InputIterator, InputIterator, ValueAllocator const&) -> template struct has_trivial_destructor_after_move > { - typedef typename ::boost::container::allocator_traits::pointer pointer; - static const bool value = ::boost::has_trivial_destructor_after_move::value && + typedef typename boost::container::list::allocator_type allocator_type; + typedef typename ::boost::container::allocator_traits::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move::value && ::boost::has_trivial_destructor_after_move::value; }; diff --git a/include/boost/container/map.hpp b/include/boost/container/map.hpp index d0c8fc9..447f4ad 100644 --- a/include/boost/container/map.hpp +++ b/include/boost/container/map.hpp @@ -1366,13 +1366,11 @@ map(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, Alloca //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations -template -struct has_trivial_destructor_after_move > +template +struct has_trivial_destructor_after_move > { - typedef typename ::boost::container::allocator_traits::pointer pointer; - static const bool value = ::boost::has_trivial_destructor_after_move::value && - ::boost::has_trivial_destructor_after_move::value && - ::boost::has_trivial_destructor_after_move::value; + typedef ::boost::container::dtl::tree, int, Compare, Allocator, Options> tree; + static const bool value = ::boost::has_trivial_destructor_after_move::value; }; namespace container { @@ -2292,13 +2290,11 @@ multimap(ordered_range_t, InputIterator, InputIterator, Compare const&, Allocato //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations -template -struct has_trivial_destructor_after_move > +template +struct has_trivial_destructor_after_move > { - typedef typename ::boost::container::allocator_traits::pointer pointer; - static const bool value = ::boost::has_trivial_destructor_after_move::value && - ::boost::has_trivial_destructor_after_move::value && - ::boost::has_trivial_destructor_after_move::value; + typedef ::boost::container::dtl::tree, int, Compare, Allocator, Options> tree; + static const bool value = ::boost::has_trivial_destructor_after_move::value; }; namespace container { diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp index 44bad8c..ca6334f 100644 --- a/include/boost/container/set.hpp +++ b/include/boost/container/set.hpp @@ -1024,13 +1024,11 @@ set(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, Alloca //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations -template +template struct has_trivial_destructor_after_move > { - typedef typename ::boost::container::allocator_traits::pointer pointer; - static const bool value = ::boost::has_trivial_destructor_after_move::value && - ::boost::has_trivial_destructor_after_move::value && - ::boost::has_trivial_destructor_after_move::value; + typedef ::boost::container::dtl::tree tree; + static const bool value = ::boost::has_trivial_destructor_after_move::value; }; namespace container { @@ -1693,10 +1691,8 @@ multiset(ordered_range_t, InputIterator, InputIterator, Compare const&, Allocato template struct has_trivial_destructor_after_move > { - typedef typename ::boost::container::allocator_traits::pointer pointer; - static const bool value = ::boost::has_trivial_destructor_after_move::value && - ::boost::has_trivial_destructor_after_move::value && - ::boost::has_trivial_destructor_after_move::value; + typedef ::boost::container::dtl::tree tree; + static const bool value = ::boost::has_trivial_destructor_after_move::value; }; namespace container { diff --git a/include/boost/container/slist.hpp b/include/boost/container/slist.hpp index a9c29f8..d10cf57 100644 --- a/include/boost/container/slist.hpp +++ b/include/boost/container/slist.hpp @@ -1696,8 +1696,9 @@ namespace boost { template struct has_trivial_destructor_after_move > { - typedef typename ::boost::container::allocator_traits::pointer pointer; - static const bool value = ::boost::has_trivial_destructor_after_move::value && + typedef typename boost::container::slist::allocator_type allocator_type; + typedef typename ::boost::container::allocator_traits::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move::value && ::boost::has_trivial_destructor_after_move::value; }; diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp index 87525f9..7d0c9b3 100644 --- a/include/boost/container/stable_vector.hpp +++ b/include/boost/container/stable_vector.hpp @@ -2183,8 +2183,9 @@ stable_vector(InputIterator, InputIterator, Allocator const&) -> template struct has_trivial_destructor_after_move > { - typedef typename ::boost::container::allocator_traits::pointer pointer; - static const bool value = ::boost::has_trivial_destructor_after_move::value && + typedef typename boost::container::stable_vector::allocator_type allocator_type; + typedef typename ::boost::container::allocator_traits::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move::value && ::boost::has_trivial_destructor_after_move::value; }; diff --git a/include/boost/container/string.hpp b/include/boost/container/string.hpp index 0943637..46ca567 100644 --- a/include/boost/container/string.hpp +++ b/include/boost/container/string.hpp @@ -3490,9 +3490,9 @@ namespace boost { template struct has_trivial_destructor_after_move > { - typedef typename ::boost::container::allocator_traits - ::allocator_type>::pointer pointer; - static const bool value = ::boost::has_trivial_destructor_after_move::value && + typedef typename boost::container::basic_string::allocator_type allocator_type; + typedef typename ::boost::container::allocator_traits::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move::value && ::boost::has_trivial_destructor_after_move::value; }; diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index d7886d5..099a878 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -3413,9 +3413,9 @@ namespace boost { template struct has_trivial_destructor_after_move > { - typedef typename ::boost::container::allocator_traits - ::type>::pointer pointer; - static const bool value = ::boost::has_trivial_destructor_after_move::value && + typedef typename boost::container::vector::allocator_type allocator_type; + typedef typename ::boost::container::allocator_traits::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move::value && ::boost::has_trivial_destructor_after_move::value; }; diff --git a/test/deque_test.cpp b/test/deque_test.cpp index 01c47e0..22b87f4 100644 --- a/test/deque_test.cpp +++ b/test/deque_test.cpp @@ -412,6 +412,34 @@ int main () } } + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // default allocator + { + typedef boost::container::deque cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits::pointer pointer; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value && + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::deque > cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits::pointer pointer; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value && + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl; + return 1; + } + } + return 0; } diff --git a/test/flat_map_test.cpp b/test/flat_map_test.cpp index 9497ee2..f5caff7 100644 --- a/test/flat_map_test.cpp +++ b/test/flat_map_test.cpp @@ -8,6 +8,9 @@ // ////////////////////////////////////////////////////////////////////////////// #include + +#include + #include #include #include @@ -22,6 +25,7 @@ #include "../../intrusive/test/iterator_test.hpp" #include +#include using namespace boost::container; @@ -557,6 +561,42 @@ bool test_heterogeneous_lookups() return true; } +// An ordered sequence of std:pair is also ordered by std::pair::first. +struct with_lookup_by_first +{ + typedef void is_transparent; + inline bool operator()(std::pair a, std::pair b) const + { + return a < b; + } + inline bool operator()(std::pair a, int first) const + { + return a.first < first; + } + inline bool operator()(int first, std::pair b) const + { + return first < b.first; + } +}; + +bool test_heterogeneous_lookup_by_partial_key() +{ + typedef flat_map,int, with_lookup_by_first> map_t; + + map_t map1; + map1[std::pair(0, 1)] = 3; + map1[std::pair(0, 2)] = 3; + + std::pair const first_0_range = map1.equal_range(0); + + if(2 != (first_0_range.second - first_0_range.first)) + return false; + + if(2 != map1.count(0)) + return false; + return true; +} + }}} //namespace boost::container::test int main() @@ -617,6 +657,9 @@ int main() if (!test_heterogeneous_lookups()) return 1; + if (!test_heterogeneous_lookup_by_partial_key()) + return 1; + //////////////////////////////////// // Testing allocator implementations //////////////////////////////////// @@ -715,6 +758,80 @@ int main() } } + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + { + typedef boost::container::dtl::pair value_t; + typedef boost::container::dtl::select1st key_of_value_t; + // flat_map, default + { + typedef boost::container::new_allocator alloc_or_cont_t; + typedef boost::container::flat_map cont; + typedef boost::container::dtl::flat_tree, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(flat_map, default) test failed" << std::endl; + return 1; + } + } + // flat_map, vector + { + typedef boost::container::vector alloc_or_cont_t; + typedef boost::container::flat_map, alloc_or_cont_t> cont; + typedef boost::container::dtl::flat_tree, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(flat_map, vector) test failed" << std::endl; + return 1; + } + } + // flat_map, std::vector + { + typedef std::vector alloc_or_cont_t; + typedef boost::container::flat_map, alloc_or_cont_t> cont; + typedef boost::container::dtl::flat_tree, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(flat_map, std::vector) test failed" << std::endl; + return 1; + } + } + // flat_multimap, default + { + typedef boost::container::new_allocator alloc_or_cont_t; + typedef boost::container::flat_multimap cont; + typedef boost::container::dtl::flat_tree, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(flat_multimap, default) test failed" << std::endl; + return 1; + } + } + // flat_multimap, vector + { + typedef boost::container::vector alloc_or_cont_t; + typedef boost::container::flat_multimap, alloc_or_cont_t> cont; + typedef boost::container::dtl::flat_tree, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(flat_multimap, vector) test failed" << std::endl; + return 1; + } + } + // flat_multimap, std::vector + { + typedef std::vector alloc_or_cont_t; + typedef boost::container::flat_multimap, alloc_or_cont_t> cont; + typedef boost::container::dtl::flat_tree, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(flat_multimap, std::vector) test failed" << std::endl; + return 1; + } + } + } + return 0; } diff --git a/test/flat_set_test.cpp b/test/flat_set_test.cpp index 7e561f7..7927b99 100644 --- a/test/flat_set_test.cpp +++ b/test/flat_set_test.cpp @@ -10,7 +10,10 @@ #include +#include #include +#include +#include #include #include @@ -574,6 +577,41 @@ bool test_heterogeneous_lookups() return true; } +// An ordered sequence of std:pair is also ordered by std::pair::first. +struct with_lookup_by_first +{ + typedef void is_transparent; + inline bool operator()(std::pair a, std::pair b) const + { + return a < b; + } + inline bool operator()(std::pair a, int first) const + { + return a.first < first; + } + inline bool operator()(int first, std::pair b) const + { + return first < b.first; + } +}; + +bool test_heterogeneous_lookup_by_partial_key() +{ + typedef flat_set, with_lookup_by_first> set_t; + + set_t set1; + set1.insert(std::pair(0, 1)); + set1.insert(std::pair(0, 2)); + + std::pair const first_0_range = set1.equal_range(0); + if(2 != (first_0_range.second - first_0_range.first)) + return false; + + if(2 != set1.count(0)) + return false; + return true; +} + }}} template @@ -715,6 +753,10 @@ int main() return 1; } + if(!test_heterogeneous_lookup_by_partial_key()){ + return 1; + } + //////////////////////////////////// // Testing allocator implementations //////////////////////////////////// @@ -813,6 +855,77 @@ int main() } } + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + { + typedef boost::container::dtl::identity key_of_value_t; + // flat_set, default + { + typedef boost::container::flat_set cont; + typedef boost::container::dtl::flat_tree, void> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(flat_set, default) test failed" << std::endl; + return 1; + } + } + // flat_set, vector + { + typedef boost::container::vector alloc_or_cont_t; + typedef boost::container::flat_set, alloc_or_cont_t> cont; + typedef boost::container::dtl::flat_tree, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(flat_set, vector) test failed" << std::endl; + return 1; + } + } + // flat_set, std::vector + { + typedef std::vector alloc_or_cont_t; + typedef boost::container::flat_set, alloc_or_cont_t> cont; + typedef boost::container::dtl::flat_tree, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(flat_set, std::vector) test failed" << std::endl; + return 1; + } + } + // flat_multiset, default + { + typedef boost::container::flat_multiset cont; + typedef boost::container::dtl::flat_tree, void> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(flat_multiset, default) test failed" << std::endl; + return 1; + } + } + // flat_multiset, vector + { + typedef boost::container::vector alloc_or_cont_t; + typedef boost::container::flat_multiset, alloc_or_cont_t> cont; + typedef boost::container::dtl::flat_tree, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(flat_multiset, vector) test failed" << std::endl; + return 1; + } + } + // flat_multiset, std::vector + { + typedef std::vector alloc_or_cont_t; + typedef boost::container::flat_multiset, alloc_or_cont_t> cont; + typedef boost::container::dtl::flat_tree, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(flat_multiset, std::vector) test failed" << std::endl; + return 1; + } + } + } + return 0; } diff --git a/test/flat_tree_test.cpp b/test/flat_tree_test.cpp index b70fb4a..e94c089 100644 --- a/test/flat_tree_test.cpp +++ b/test/flat_tree_test.cpp @@ -12,6 +12,8 @@ #include #include +#include + #include "movable_int.hpp" #include "dummy_test_allocator.hpp" @@ -120,5 +122,35 @@ template class flat_tree int main () { + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // default + { + typedef boost::container::dtl::flat_tree, + std::less, void> tree; + typedef tree::container_type container_type; + typedef tree::key_compare key_compare; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value && + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::dtl::flat_tree, + std::less, std::allocator > tree; + typedef tree::container_type container_type; + typedef tree::key_compare key_compare; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value && + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl; + return 1; + } + } + return 0; } diff --git a/test/list_test.cpp b/test/list_test.cpp index 5006a7d..c4f9f41 100644 --- a/test/list_test.cpp +++ b/test/list_test.cpp @@ -252,6 +252,34 @@ int main () } #endif + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // default allocator + { + typedef boost::container::list cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits::pointer pointer; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value && + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::list > cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits::pointer pointer; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value && + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl; + return 1; + } + } + return 0; } diff --git a/test/map_test.cpp b/test/map_test.cpp index b73f569..7448303 100644 --- a/test/map_test.cpp +++ b/test/map_test.cpp @@ -633,6 +633,60 @@ int main () BOOST_STATIC_ASSERT(sizeof(rbmmap_size_optimized_yes) < sizeof(rbmap_size_optimized_no)); BOOST_STATIC_ASSERT(sizeof(avlmap_size_optimized_yes) < sizeof(avlmmap_size_optimized_no)); + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + { + typedef std::pair value_type; + // + // map + // + // default allocator + { + typedef boost::container::map cont; + typedef boost::container::dtl::tree, void, void> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(map, default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::map, std::allocator > cont; + typedef boost::container::dtl::tree, std::allocator, void> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(map, std::allocator) test failed" << std::endl; + return 1; + } + } + // + // multimap + // + // default allocator + { + // default allocator + typedef boost::container::multimap cont; + typedef boost::container::dtl::tree, void, void> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(multimap, default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::multimap, std::allocator > cont; + typedef boost::container::dtl::tree, std::allocator, void> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(multimap, std::allocator) test failed" << std::endl; + return 1; + } + } + } + return 0; } diff --git a/test/set_test.cpp b/test/set_test.cpp index 39ab1b7..a7d0b47 100644 --- a/test/set_test.cpp +++ b/test/set_test.cpp @@ -605,6 +605,50 @@ int main () if(!node_type_test()) return 1; + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // set, default allocator + { + typedef boost::container::set cont; + typedef boost::container::dtl::tree, void, void> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(set, default allocator) test failed" << std::endl; + return 1; + } + } + // set, std::allocator + { + typedef boost::container::set, std::allocator > cont; + typedef boost::container::dtl::tree, std::allocator, void> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(set, std::allocator) test failed" << std::endl; + return 1; + } + } + // multiset, default allocator + { + typedef boost::container::multiset cont; + typedef boost::container::dtl::tree, void, void> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(multiset, default allocator) test failed" << std::endl; + return 1; + } + } + // multiset, std::allocator + { + typedef boost::container::multiset, std::allocator > cont; + typedef boost::container::dtl::tree, std::allocator, void> tree; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(multiset, std::allocator) test failed" << std::endl; + return 1; + } + } + return 0; } diff --git a/test/slist_test.cpp b/test/slist_test.cpp index 4e09837..0894344 100644 --- a/test/slist_test.cpp +++ b/test/slist_test.cpp @@ -255,6 +255,34 @@ int main () } #endif + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // default allocator + { + typedef boost::container::slist cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits::pointer pointer; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value && + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::slist > cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits::pointer pointer; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value && + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl; + return 1; + } + } + return 0; } diff --git a/test/small_vector_options_test.cpp b/test/small_vector_options_test.cpp new file mode 100644 index 0000000..73e4855 --- /dev/null +++ b/test/small_vector_options_test.cpp @@ -0,0 +1,110 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-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 +using namespace boost::container; + +const std::size_t Capacity = 10u; + +void test_alignment() +{ + { //extended alignment + const std::size_t extended_alignment = sizeof(int)*4u; + BOOST_STATIC_ASSERT(extended_alignment > dtl::alignment_of::value); + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = small_vector_options_t< inplace_alignment >; + #else + typedef small_vector_options + < inplace_alignment >::type options_t; + #endif + + small_vector v; + v.resize(v.capacity()); + BOOST_ASSERT((reinterpret_cast(&v[0]) % extended_alignment) == 0); + } + { //default alignment + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = small_vector_options_t< inplace_alignment<0> >; + #else + typedef small_vector_options< inplace_alignment<0> >::type options_t; + #endif + + small_vector v; + v.resize(v.capacity()); + BOOST_ASSERT((reinterpret_cast(&v[0]) % dtl::alignment_of::value) == 0); + } +} + +void test_growth_factor_50() +{ + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = small_vector_options_t< growth_factor >; + #else + typedef small_vector_options + < growth_factor >::type options_t; + #endif + + small_vector, options_t> v; + + v.resize(5); + v.resize(v.capacity()); + std::size_t old_capacity = v.capacity(); + v.push_back(0); + std::size_t new_capacity = v.capacity(); + BOOST_TEST(new_capacity == old_capacity + old_capacity/2); +} + +void test_growth_factor_60() +{ + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = small_vector_options_t< growth_factor >; + #else + typedef small_vector_options + < growth_factor >::type options_t; + #endif + + small_vector, options_t> v; + + v.resize(5); + v.resize(v.capacity()); + std::size_t old_capacity = v.capacity(); + v.push_back(0); + std::size_t new_capacity = v.capacity(); + BOOST_TEST(new_capacity == old_capacity + 3*old_capacity/5); +} + +void test_growth_factor_100() +{ + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = small_vector_options_t< growth_factor >; + #else + typedef small_vector_options + < growth_factor >::type options_t; + #endif + + small_vector, options_t> v; + + v.resize(5); + v.resize(v.capacity()); + std::size_t old_capacity = v.capacity(); + v.push_back(0); + std::size_t new_capacity = v.capacity(); + BOOST_TEST(new_capacity == 2*old_capacity); +} + +int main() +{ + test_alignment(); + test_growth_factor_50(); + test_growth_factor_60(); + test_growth_factor_100(); + return ::boost::report_errors(); +} diff --git a/test/small_vector_test.cpp b/test/small_vector_test.cpp index e3b7600..315d64d 100644 --- a/test/small_vector_test.cpp +++ b/test/small_vector_test.cpp @@ -212,5 +212,25 @@ int main() } } + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // default allocator + { + typedef boost::container::small_vector cont; + if (boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::small_vector > cont; + if (boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl; + return 1; + } + } + return 0; } diff --git a/test/stable_vector_test.cpp b/test/stable_vector_test.cpp index fd76330..e0fb586 100644 --- a/test/stable_vector_test.cpp +++ b/test/stable_vector_test.cpp @@ -193,6 +193,34 @@ int main() } #endif + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // default allocator + { + typedef boost::container::stable_vector cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits::pointer pointer; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value && + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::stable_vector > cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits::pointer pointer; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value && + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl; + return 1; + } + } + return 0; } diff --git a/test/static_vector_options_test.cpp b/test/static_vector_options_test.cpp new file mode 100644 index 0000000..e8965d5 --- /dev/null +++ b/test/static_vector_options_test.cpp @@ -0,0 +1,124 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-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. +// +////////////////////////////////////////////////////////////////////////////// +#define BOOST_ENABLE_ASSERT_HANDLER +#include +#include +#include //for bad_alloc +#include +using namespace boost::container; + +//User-defined assertion to test throw_on_overflow +struct throw_on_overflow_off +{}; + +namespace boost { + void assertion_failed(char const *, char const *, char const *, long) + { + throw throw_on_overflow_off(); + } + + void assertion_failed_msg(char const *, char const *, char const *, char const *, long ) + { + throw throw_on_overflow_off(); + } +} + +void test_alignment() +{ + const std::size_t Capacity = 10u; + { //extended alignment + const std::size_t extended_alignment = sizeof(int)*4u; + BOOST_STATIC_ASSERT(extended_alignment > dtl::alignment_of::value); + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = static_vector_options_t< inplace_alignment >; + #else + typedef static_vector_options + < inplace_alignment >::type options_t; + #endif + + static_vector v; + v.resize(v.capacity()); + BOOST_ASSERT((reinterpret_cast(&v[0]) % extended_alignment) == 0); + } + { //default alignment + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = static_vector_options_t< inplace_alignment<0> >; + #else + typedef static_vector_options< inplace_alignment<0> >::type options_t; + #endif + + static_vector v; + v.resize(v.capacity()); + BOOST_ASSERT((reinterpret_cast(&v[0]) % dtl::alignment_of::value) == 0); + } +} + +void test_throw_on_overflow() +{ + #if !defined(BOOST_NO_EXCEPTIONS) + const std::size_t Capacity = 10u; + { //throw_on_overflow == true, expect bad_alloc + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = static_vector_options_t< throw_on_overflow >; + #else + typedef static_vector_options + < throw_on_overflow >::type options_t; + #endif + + static_vector v; + + v.resize(Capacity); + bool expected_type_thrown = false; + try{ + v.push_back(0); + } + catch(std::bad_alloc&) + { + expected_type_thrown = true; + } + catch(...) + {} + BOOST_TEST(expected_type_thrown == true); + BOOST_TEST(v.capacity() == Capacity); + } + { //throw_on_overflow == false, test it through BOOST_ASSERT + //even in release mode (BOOST_ENABLE_ASSERT_HANDLER), and throwing + //a special type in that assertion. + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = static_vector_options_t< throw_on_overflow >; + #else + typedef static_vector_options< throw_on_overflow >::type options_t; + #endif + + static_vector v; + + v.resize(Capacity); + bool expected_type_thrown = false; + try{ + v.push_back(0); + } + catch(throw_on_overflow_off) + { + expected_type_thrown = true; + } + catch(...) + {} + BOOST_TEST(expected_type_thrown == true); + BOOST_TEST(v.capacity() == Capacity); + } + #endif +} + +int main() +{ + test_alignment(); + test_throw_on_overflow(); + return ::boost::report_errors(); +} diff --git a/test/string_test.cpp b/test/string_test.cpp index 2dfb2a4..b2d17f6 100644 --- a/test/string_test.cpp +++ b/test/string_test.cpp @@ -562,6 +562,34 @@ int main() return 1; } + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // default allocator + { + typedef boost::container::basic_string cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits::pointer pointer; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value && + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::basic_string, std::allocator > cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits::pointer pointer; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value && + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl; + return 1; + } + } + return boost::report_errors(); } diff --git a/test/tree_test.cpp b/test/tree_test.cpp index c1a1c3d..e075596 100644 --- a/test/tree_test.cpp +++ b/test/tree_test.cpp @@ -9,6 +9,10 @@ ////////////////////////////////////////////////////////////////////////////// #include #include +#include +#include + +#include #include "movable_int.hpp" #include "dummy_test_allocator.hpp" @@ -79,5 +83,37 @@ template class tree int main () { + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // default + { + typedef boost::container::dtl::tree, void, void> tree; + typedef tree::allocator_type allocator_type; + typedef boost::container::allocator_traits::pointer pointer; + typedef tree::key_compare key_compare; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value && + boost::has_trivial_destructor_after_move::value && + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::dtl::tree, std::allocator, void> tree; + typedef tree::allocator_type allocator_type; + typedef boost::container::allocator_traits::pointer pointer; + typedef tree::key_compare key_compare; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value && + boost::has_trivial_destructor_after_move::value && + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl; + return 1; + } + } + return 0; } diff --git a/test/vector_test.cpp b/test/vector_test.cpp index 2420563..c9b82cc 100644 --- a/test/vector_test.cpp +++ b/test/vector_test.cpp @@ -332,5 +332,33 @@ int main() return 1; } + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // default allocator + { + typedef boost::container::vector cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits::pointer pointer; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value && + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::vector > cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits::pointer pointer; + if (boost::has_trivial_destructor_after_move::value != + boost::has_trivial_destructor_after_move::value && + boost::has_trivial_destructor_after_move::value) { + std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl; + return 1; + } + } + return 0; }