diff --git a/include/boost/container/detail/construct_in_place.hpp b/include/boost/container/detail/construct_in_place.hpp index 62cb3c3..d824d81 100644 --- a/include/boost/container/detail/construct_in_place.hpp +++ b/include/boost/container/detail/construct_in_place.hpp @@ -30,6 +30,8 @@ namespace container { //In place construction +struct iterator_arg_t{}; + template BOOST_CONTAINER_FORCEINLINE void construct_in_place(Allocator &a, T* dest, InpIt source) { boost::container::allocator_traits::construct(a, dest, *source); } diff --git a/include/boost/container/detail/destroyers.hpp b/include/boost/container/detail/destroyers.hpp index ac9aa3b..45bc431 100644 --- a/include/boost/container/detail/destroyers.hpp +++ b/include/boost/container/detail/destroyers.hpp @@ -135,7 +135,7 @@ struct null_scoped_array_deallocator }; template -struct scoped_destroy_deallocator +struct scoped_node_destroy_deallocator { typedef boost::container::allocator_traits AllocTraits; typedef typename AllocTraits::pointer pointer; @@ -143,13 +143,13 @@ struct scoped_destroy_deallocator boost::container::dtl:: version::value> alloc_version; - scoped_destroy_deallocator(pointer p, Allocator& a) + scoped_node_destroy_deallocator(pointer p, Allocator& a) : m_ptr(p), m_alloc(a) {} - ~scoped_destroy_deallocator() + ~scoped_node_destroy_deallocator() { if(m_ptr){ - AllocTraits::destroy(m_alloc, boost::movelib::to_raw_pointer(m_ptr)); + boost::movelib::to_raw_pointer(m_ptr)->destructor(m_alloc); priv_deallocate(m_ptr, alloc_version()); } } @@ -355,7 +355,7 @@ class value_destructor }; template -class allocator_destroyer +class allocator_node_destroyer { typedef boost::container::allocator_traits AllocTraits; typedef typename AllocTraits::value_type value_type; @@ -375,19 +375,51 @@ class allocator_destroyer { a_.deallocate_one(p); } public: - BOOST_CONTAINER_FORCEINLINE explicit allocator_destroyer(Allocator &a) + BOOST_CONTAINER_FORCEINLINE explicit allocator_node_destroyer(Allocator &a) : a_(a) {} BOOST_CONTAINER_FORCEINLINE void operator()(const pointer &p) { - AllocTraits::destroy(a_, boost::movelib::to_raw_pointer(p)); + boost::movelib::to_raw_pointer(p)->destructor(a_); this->priv_deallocate(p, alloc_version()); } }; +template +class scoped_node_destructor +{ + typedef boost::container::allocator_traits AllocTraits; + public: + typedef typename Allocator::value_type value_type; + BOOST_CONTAINER_FORCEINLINE scoped_node_destructor(Allocator &a, value_type *pv) + : pv_(pv), a_(a) + {} + + BOOST_CONTAINER_FORCEINLINE ~scoped_node_destructor() + { + if(pv_){ + pv_->destructor(a_); + } + } + + BOOST_CONTAINER_FORCEINLINE void release() + { pv_ = 0; } + + + BOOST_CONTAINER_FORCEINLINE void set(value_type *ptr) { pv_ = ptr; } + + BOOST_CONTAINER_FORCEINLINE value_type *get() const { return pv_; } + + private: + value_type *pv_; + Allocator &a_; +}; + + + template -class allocator_destroyer_and_chain_builder +class allocator_node_destroyer_and_chain_builder { typedef allocator_traits allocator_traits_type; typedef typename allocator_traits_type::value_type value_type; @@ -397,13 +429,13 @@ class allocator_destroyer_and_chain_builder multiallocation_chain &c_; public: - BOOST_CONTAINER_FORCEINLINE allocator_destroyer_and_chain_builder(Allocator &a, multiallocation_chain &c) + BOOST_CONTAINER_FORCEINLINE allocator_node_destroyer_and_chain_builder(Allocator &a, multiallocation_chain &c) : a_(a), c_(c) {} BOOST_CONTAINER_FORCEINLINE void operator()(const typename Allocator::pointer &p) { - allocator_traits::destroy(a_, boost::movelib::to_raw_pointer(p)); + boost::movelib::to_raw_pointer(p)->destructor(a_); c_.push_back(p); } }; @@ -414,7 +446,7 @@ class allocator_multialloc_chain_node_deallocator typedef allocator_traits allocator_traits_type; typedef typename allocator_traits_type::value_type value_type; typedef typename Allocator::multiallocation_chain multiallocation_chain; - typedef allocator_destroyer_and_chain_builder chain_builder; + typedef allocator_node_destroyer_and_chain_builder chain_builder; Allocator & a_; multiallocation_chain c_; diff --git a/include/boost/container/detail/dispatch_uses_allocator.hpp b/include/boost/container/detail/dispatch_uses_allocator.hpp index 24f0316..800b1b3 100644 --- a/include/boost/container/detail/dispatch_uses_allocator.hpp +++ b/include/boost/container/detail/dispatch_uses_allocator.hpp @@ -23,11 +23,13 @@ #include #include -#include +#include #include #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #include +#else +#include #endif #include diff --git a/include/boost/container/detail/is_pair.hpp b/include/boost/container/detail/is_pair.hpp new file mode 100644 index 0000000..e208a5c --- /dev/null +++ b/include/boost/container/detail/is_pair.hpp @@ -0,0 +1,83 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-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. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_IS_PAIR_HPP +#define BOOST_CONTAINER_CONTAINER_DETAIL_IS_PAIR_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +namespace boost { +namespace tuples { + +struct null_type; + +template < + class T0, class T1, class T2, + class T3, class T4, class T5, + class T6, class T7, class T8, + class T9> +class tuple; + +} //namespace tuples { +} //namespace boost { + +namespace boost { +namespace container { + +struct try_emplace_t{}; + +namespace dtl { + +template +struct pair; + +template +struct is_pair +{ + static const bool value = false; +}; + +template +struct is_pair< pair > +{ + static const bool value = true; +}; + +template +struct is_pair< std::pair > +{ + static const bool value = true; +}; + +template +struct is_not_pair +{ + static const bool value = !is_pair::value; +}; + +} //namespace dtl { +} //namespace container { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_IS_PAIR_HPP diff --git a/include/boost/container/detail/node_alloc_holder.hpp b/include/boost/container/detail/node_alloc_holder.hpp index 852c463..bb2cdc9 100644 --- a/include/boost/container/detail/node_alloc_holder.hpp +++ b/include/boost/container/detail/node_alloc_holder.hpp @@ -36,6 +36,7 @@ #include #include #include +#include // intrusive #include #include @@ -50,6 +51,140 @@ namespace boost { namespace container { + +//This trait is used to type-pun std::pair because in C++03 +//compilers std::pair is useless for C++11 features +template::value > +struct node_internal_data_type +{ + typedef T type; +}; + +template +struct node_internal_data_type< T, true> +{ + typedef dtl::pair< typename dtl::remove_const::type + , typename T::second_type> + type; +}; + +template +struct base_node + : public HookDefiner::type +{ + public: + typedef T value_type; + typedef typename node_internal_data_type::type internal_type; + typedef typename HookDefiner::type hook_type; + + typedef typename dtl::aligned_storage::value>::type storage_t; + storage_t m_storage; + + #if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" + #define BOOST_CONTAINER_DISABLE_ALIASING_WARNING + # endif + public: + + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + template + explicit base_node(Alloc &a, Args &&...args) + : hook_type() + { + ::boost::container::allocator_traits::construct + (a, &this->get_real_data(), ::boost::forward(args)...); + } + + #else //defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + #define BOOST_CONTAINER_BASE_NODE_CONSTRUCT_IMPL(N) \ + template< class Alloc BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \ + explicit base_node(Alloc &a BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + : hook_type()\ + {\ + ::boost::container::allocator_traits::construct\ + (a, &this->get_real_data() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ + }\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_BASE_NODE_CONSTRUCT_IMPL) + #undef BOOST_CONTAINER_BASE_NODE_CONSTRUCT_IMPL + + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + template + explicit base_node(iterator_arg_t, Alloc &a, It it) + : hook_type() + { + ::boost::container::construct_in_place(a, &this->get_real_data(), it); + } + + BOOST_CONTAINER_FORCEINLINE T &get_data() + { return *move_detail::force_ptr(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE const T &get_data() const + { return *move_detail::force_ptr(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE internal_type &get_real_data() + { return *move_detail::force_ptr(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE const internal_type &get_real_data() const + { return *move_detail::force_ptr(this->m_storage.data); } + + #if defined(BOOST_CONTAINER_DISABLE_ALIASING_WARNING) + #pragma GCC diagnostic pop + #undef BOOST_CONTAINER_DISABLE_ALIASING_WARNING + # endif + + template + void destructor(Alloc &a) BOOST_NOEXCEPT + { + allocator_traits::destroy + (a, &this->get_real_data()); + this->~base_node(); + } + + template + BOOST_CONTAINER_FORCEINLINE + typename dtl::enable_if< dtl::is_pair, void >::type + do_assign(const Pair &p) + { + typedef typename Pair::first_type first_type; + const_cast::type &>(this->get_real_data().first) = p.first; + this->get_real_data().second = p.second; + } + + template + BOOST_CONTAINER_FORCEINLINE + typename dtl::disable_if< dtl::is_pair, void >::type + do_assign(const V &v) + { this->get_real_data() = v; } + + template + BOOST_CONTAINER_FORCEINLINE + typename dtl::enable_if< dtl::is_pair, void >::type + do_move_assign(Pair &p) + { + typedef typename Pair::first_type first_type; + const_cast(this->get_real_data().first) = ::boost::move(p.first); + this->get_real_data().second = ::boost::move(p.second); + } + + template + BOOST_CONTAINER_FORCEINLINE + typename dtl::disable_if< dtl::is_pair, void >::type + do_move_assign(V &v) + { this->get_real_data() = ::boost::move(v); } + + private: + base_node(); + + BOOST_CONTAINER_FORCEINLINE ~base_node() + { } +}; + + namespace dtl { BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(key_compare) @@ -111,7 +246,7 @@ struct node_alloc_holder version::value> alloc_version; typedef typename ICont::iterator icont_iterator; typedef typename ICont::const_iterator icont_citerator; - typedef allocator_destroyer Destroyer; + typedef allocator_node_destroyer Destroyer; typedef allocator_traits NodeAllocTraits; typedef allocator_version_traits AllocVersionTraits; @@ -176,7 +311,7 @@ struct node_alloc_holder {} explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x) - : NodeAlloc(boost::move(x.node_alloc())) + : NodeAlloc(boost::move(BOOST_MOVE_TO_LV(x).node_alloc())) { this->icont().swap(x.icont()); } explicit node_alloc_holder(const val_compare &c) @@ -185,15 +320,15 @@ struct node_alloc_holder //helpers for move assignments explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const val_compare &c) - : NodeAlloc(boost::move(x.node_alloc())), m_icont(typename ICont::key_compare(c)) + : NodeAlloc(boost::move(BOOST_MOVE_TO_LV(x).node_alloc())), m_icont(typename ICont::key_compare(c)) { this->icont().swap(x.icont()); } explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const val_hasher &hf, const val_equal &eql) - : NodeAlloc(boost::move(x.node_alloc())) + : NodeAlloc(boost::move(BOOST_MOVE_TO_LV(x).node_alloc())) , m_icont( typename ICont::bucket_traits() , typename ICont::hasher(hf) , typename ICont::key_equal(eql)) - { this->icont().swap(x.icont()); } + { this->icont().swap(BOOST_MOVE_TO_LV(x).icont()); } void copy_assign_alloc(const node_alloc_holder &x) { @@ -227,18 +362,11 @@ struct node_alloc_holder NodePtr create_node(Args &&...args) { NodePtr p = this->allocate_one(); - BOOST_TRY{ - ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) Node; - allocator_traits::construct - (this->node_alloc() - , p->get_real_data_ptr(), boost::forward(args)...); - } - BOOST_CATCH(...) { - p->destroy_header(); - this->node_alloc().deallocate(p, 1); - BOOST_RETHROW - } - BOOST_CATCH_END + NodeAlloc &nalloc = this->node_alloc(); + Deallocator node_deallocator(p, nalloc); + ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) + Node(nalloc, boost::forward(args)...); + node_deallocator.release(); return (p); } @@ -249,19 +377,11 @@ struct node_alloc_holder NodePtr create_node(BOOST_MOVE_UREF##N)\ {\ NodePtr p = this->allocate_one();\ - BOOST_TRY{\ - ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) Node;\ - allocator_traits::construct\ - ( this->node_alloc()\ - , p->get_real_data_ptr()\ - BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ - }\ - BOOST_CATCH(...) {\ - p->destroy_header();\ - this->node_alloc().deallocate(p, 1);\ - BOOST_RETHROW\ - }\ - BOOST_CATCH_END\ + NodeAlloc &nalloc = this->node_alloc();\ + Deallocator node_deallocator(p, nalloc);\ + ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t())\ + Node(nalloc BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ + node_deallocator.release();\ return (p);\ }\ // @@ -274,16 +394,11 @@ struct node_alloc_holder NodePtr create_node_from_it(const It &it) { NodePtr p = this->allocate_one(); - BOOST_TRY{ - ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) Node; - ::boost::container::construct_in_place(this->node_alloc(), p->get_real_data_ptr(), it); - } - BOOST_CATCH(...) { - p->destroy_header(); - this->node_alloc().deallocate(p, 1); - BOOST_RETHROW - } - BOOST_CATCH_END + NodeAlloc &nalloc = this->node_alloc(); + Deallocator node_deallocator(p, nalloc); + ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) + Node(iterator_arg_t(), nalloc, it); + node_deallocator.release(); return (p); } @@ -316,7 +431,7 @@ struct node_alloc_holder void destroy_node(const NodePtr &nodep) { - allocator_traits::destroy(this->node_alloc(), boost::movelib::to_raw_pointer(nodep)); + boost::movelib::to_raw_pointer(nodep)->destructor(this->node_alloc()); this->deallocate_one(nodep); } @@ -346,28 +461,25 @@ struct node_alloc_holder Node *p = 0; BOOST_TRY{ Deallocator node_deallocator(NodePtr(), nalloc); - dtl::scoped_destructor sdestructor(nalloc, 0); + dtl::scoped_node_destructor sdestructor(nalloc, 0); while(n){ --n; p = boost::movelib::iterator_to_raw_pointer(itbeg); ++itbeg; //Increment iterator before overwriting pointed memory //This does not throw - p = ::new(p, boost_container_new_t()) Node; - node_deallocator.set(p); - //This can throw - boost::container::construct_in_place(nalloc, p->get_real_data_ptr(), beg); + ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) + Node(iterator_arg_t(), nalloc, beg); sdestructor.set(p); ++beg; //This can throw in some containers (predicate might throw). //(sdestructor will destruct the node and node_deallocator will deallocate it in case of exception) inserter(*p); - sdestructor.set(0); + sdestructor.release(); } sdestructor.release(); node_deallocator.release(); } BOOST_CATCH(...){ - p->destroy_header(); chain.incorporate_after(chain.last(), &*itbeg, &*itlast, n); node_allocator_version_traits_type::deallocate_individual(this->node_alloc(), chain); BOOST_RETHROW @@ -382,7 +494,7 @@ struct node_alloc_holder void clear(version_2) { typename NodeAlloc::multiallocation_chain chain; - allocator_destroyer_and_chain_builder builder(this->node_alloc(), chain); + allocator_node_destroyer_and_chain_builder builder(this->node_alloc(), chain); this->icont().clear_and_dispose(builder); //BOOST_STATIC_ASSERT((::boost::has_move_emulation_enabled::value == true)); if(!chain.empty()) @@ -396,7 +508,7 @@ struct node_alloc_holder { NodeAlloc & nalloc = this->node_alloc(); typename NodeAlloc::multiallocation_chain chain; - allocator_destroyer_and_chain_builder chain_builder(nalloc, chain); + allocator_node_destroyer_and_chain_builder chain_builder(nalloc, chain); icont_iterator ret_it = this->icont().erase_and_dispose(first, last, chain_builder); nalloc.deallocate_individual(chain); return ret_it; diff --git a/include/boost/container/detail/pair.hpp b/include/boost/container/detail/pair.hpp index 449e093..89b7876 100644 --- a/include/boost/container/detail/pair.hpp +++ b/include/boost/container/detail/pair.hpp @@ -22,6 +22,7 @@ #endif #include +#include #include #include @@ -29,6 +30,7 @@ #include #include #include +#include #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) # include #endif @@ -38,21 +40,6 @@ #include #include -namespace boost { -namespace tuples { - -struct null_type; - -template < - class T0, class T1, class T2, - class T3, class T4, class T5, - class T6, class T7, class T8, - class T9> -class tuple; - -} //namespace tuples { -} //namespace boost { - namespace boost { namespace container { namespace pair_impl { @@ -116,10 +103,6 @@ namespace container { ::std::piecewise_construct_t *std_piecewise_construct_holder::dummy = reinterpret_cast< ::std::piecewise_construct_t *>(0x01234); //Avoid sanitizer errors on references to null pointers -typedef const std::piecewise_construct_t & piecewise_construct_t; - -struct try_emplace_t{}; - #else //! The piecewise_construct_t struct is an empty structure type used as a unique type to @@ -143,45 +126,6 @@ struct piecewise_construct_use { (void)&::boost::container::piecewise_construct; } }; -template -struct pair; - -template -struct is_pair -{ - static const bool value = false; -}; - -template -struct is_pair< pair > -{ - static const bool value = true; -}; - -template -struct is_pair< std::pair > -{ - static const bool value = true; -}; - -template -struct is_not_pair -{ - static const bool value = !is_pair::value; -}; - -template -struct is_std_pair -{ - static const bool value = false; -}; - -template -struct is_std_pair< std::pair > -{ - static const bool value = true; -}; - struct pair_nat; template diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index ac72e57..051eb10 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -121,104 +121,9 @@ struct tree_internal_data_type< std::pair > typedef pair::type, T2> type; }; -//The node to be store in the tree template -struct tree_node - : public intrusive_tree_hook::type +struct iiterator_node_value_type< base_node > > { - public: - typedef typename intrusive_tree_hook - ::type hook_type; - typedef T value_type; - typedef typename tree_internal_data_type::type internal_type; - - typedef tree_node< T, VoidPointer - , tree_type_value, OptimizeSize> node_t; - - typedef typename boost::container::dtl::aligned_storage - ::value>::type storage_t; - storage_t m_storage; - - #if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wstrict-aliasing" - #define BOOST_CONTAINER_DISABLE_ALIASING_WARNING - # endif - - BOOST_CONTAINER_FORCEINLINE T &get_data() - { return *move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE const T &get_data() const - { return *move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE T *get_data_ptr() - { return move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE const T *get_data_ptr() const - { return move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE internal_type &get_real_data() - { return *move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE const internal_type &get_real_data() const - { return *move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE internal_type *get_real_data_ptr() - { return move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE const internal_type *get_real_data_ptr() const - { return move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE ~tree_node() - { move_detail::force_ptr(this->m_storage.data)->~internal_type(); } - - #if defined(BOOST_CONTAINER_DISABLE_ALIASING_WARNING) - #pragma GCC diagnostic pop - #undef BOOST_CONTAINER_DISABLE_ALIASING_WARNING - # endif - - BOOST_CONTAINER_FORCEINLINE void destroy_header() - { static_cast(this)->~hook_type(); } - - template - BOOST_CONTAINER_FORCEINLINE void do_assign(const std::pair &p) - { - const_cast(this->get_real_data().first) = p.first; - this->get_real_data().second = p.second; - } - - template - BOOST_CONTAINER_FORCEINLINE void do_assign(const pair &p) - { - const_cast(this->get_real_data().first) = p.first; - this->get_real_data().second = p.second; - } - - template - BOOST_CONTAINER_FORCEINLINE void do_assign(const V &v) - { this->get_real_data() = v; } - - template - BOOST_CONTAINER_FORCEINLINE void do_move_assign(std::pair &p) - { - const_cast(this->get_real_data().first) = ::boost::move(p.first); - this->get_real_data().second = ::boost::move(p.second); - } - - template - BOOST_CONTAINER_FORCEINLINE void do_move_assign(pair &p) - { - const_cast(this->get_real_data().first) = ::boost::move(p.first); - this->get_real_data().second = ::boost::move(p.second); - } - - template - BOOST_CONTAINER_FORCEINLINE void do_move_assign(V &v) - { this->get_real_data() = ::boost::move(v); } -}; - -template -struct iiterator_node_value_type< tree_node > { typedef T type; }; @@ -321,9 +226,8 @@ struct intrusive_tree_type allocator_traits::void_pointer void_pointer; typedef typename boost::container:: allocator_traits::size_type size_type; - typedef typename dtl::tree_node - < value_type, void_pointer - , tree_type_value, OptimizeSize> node_t; + typedef base_node > node_t; typedef value_to_node_compare node_compare_type; //Deducing the hook type from node_t (e.g. node_t::hook_type) would @@ -388,10 +292,10 @@ class RecyclingCloner : m_holder(holder), m_icont(itree) {} - BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, node_t &other, bool_) + BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type p, node_t &other, bool_) { p->do_move_assign(other.get_real_data()); } - BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_t &other, bool_) + BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type p, const node_t &other, bool_) { p->do_assign(other.get_real_data()); } node_ptr_type operator() @@ -440,7 +344,7 @@ struct key_node_compare template BOOST_CONTAINER_FORCEINLINE static const key_type & - key_from(const tree_node &n) + key_from(const base_node > &n) { return key_of_value()(n.get_data()); } @@ -505,7 +409,7 @@ struct real_key_of_value, int> }; template -struct real_key_of_value, int> +struct real_key_of_value, int> { typedef dtl::select1st type; }; @@ -552,7 +456,7 @@ class tree typedef typename AllocHolder::Node Node; typedef typename Icont::iterator iiterator; typedef typename Icont::const_iterator iconst_iterator; - typedef dtl::allocator_destroyer Destroyer; + typedef dtl::allocator_node_destroyer Destroyer; typedef typename AllocHolder::alloc_version alloc_version; typedef intrusive_tree_proxy intrusive_tree_proxy_t; @@ -1000,7 +904,7 @@ class tree (BOOST_FWD_REF(MovableConvertible) v, insert_commit_data &data) { NodePtr tmp = AllocHolder::create_node(boost::forward(v)); - scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); + scoped_node_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); iterator ret(this->icont().insert_unique_commit(*tmp, data)); destroy_deallocator.release(); return ret; @@ -1038,7 +942,7 @@ class tree (BOOST_FWD_REF(KeyConvertible) key, BOOST_FWD_REF(M) obj, insert_commit_data &data) { NodePtr tmp = AllocHolder::create_node(boost::forward(key), boost::forward(obj)); - scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); + scoped_node_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); iiterator ret(this->icont().insert_unique_commit(*tmp, data)); destroy_deallocator.release(); return ret; @@ -1065,7 +969,7 @@ class tree { value_type &v = p->get_data(); insert_commit_data data; - scoped_destroy_deallocator destroy_deallocator(p, this->node_alloc()); + scoped_node_destroy_deallocator destroy_deallocator(p, this->node_alloc()); std::pair ret = this->insert_unique_check(key_of_value_t()(v), data); if(!ret.second){ @@ -1109,7 +1013,7 @@ class tree iterator emplace_equal(BOOST_FWD_REF(Args)... args) { NodePtr tmp(AllocHolder::create_node(boost::forward(args)...)); - scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); + scoped_node_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); destroy_deallocator.release(); return ret; @@ -1120,7 +1024,7 @@ class tree { BOOST_ASSERT((priv_is_linked)(hint)); NodePtr tmp(AllocHolder::create_node(boost::forward(args)...)); - scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); + scoped_node_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); iterator ret(this->icont().insert_equal(hint.get(), *tmp)); destroy_deallocator.release(); return ret; @@ -1157,7 +1061,7 @@ class tree iterator emplace_equal(BOOST_MOVE_UREF##N)\ {\ NodePtr tmp(AllocHolder::create_node(BOOST_MOVE_FWD##N));\ - scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc());\ + scoped_node_destroy_deallocator destroy_deallocator(tmp, this->node_alloc());\ iterator ret(this->icont().insert_equal(this->icont().end(), *tmp));\ destroy_deallocator.release();\ return ret;\ @@ -1168,7 +1072,7 @@ class tree {\ BOOST_ASSERT((priv_is_linked)(hint));\ NodePtr tmp(AllocHolder::create_node(BOOST_MOVE_FWD##N));\ - scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc());\ + scoped_node_destroy_deallocator destroy_deallocator(tmp, this->node_alloc());\ iterator ret(this->icont().insert_equal(hint.get(), *tmp));\ destroy_deallocator.release();\ return ret;\ @@ -1208,7 +1112,7 @@ class tree iterator insert_equal_convertible(BOOST_FWD_REF(MovableConvertible) v) { NodePtr tmp(AllocHolder::create_node(boost::forward(v))); - scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); + scoped_node_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); destroy_deallocator.release(); return ret; @@ -1219,7 +1123,7 @@ class tree { BOOST_ASSERT((priv_is_linked)(hint)); NodePtr tmp(AllocHolder::create_node(boost::forward(v))); - scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); + scoped_node_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); iterator ret(this->icont().insert_equal(hint.get(), *tmp)); destroy_deallocator.release(); return ret; diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp index cb680a6..88fa4c3 100644 --- a/include/boost/container/list.hpp +++ b/include/boost/container/list.hpp @@ -69,61 +69,8 @@ struct list_hook }; template -struct list_node - : public list_hook::type +struct iiterator_node_value_type< base_node > > { - public: - typedef T value_type; - typedef T internal_type; - typedef typename list_hook::type hook_type; - - typedef typename dtl::aligned_storage::value>::type storage_t; - storage_t m_storage; - - #if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wstrict-aliasing" - #define BOOST_CONTAINER_DISABLE_ALIASING_WARNING - # endif - - BOOST_CONTAINER_FORCEINLINE T &get_data() - { return *move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE const T &get_data() const - { return *move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE T *get_data_ptr() - { return move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE const T *get_data_ptr() const - { return move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE internal_type &get_real_data() - { return *move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE const internal_type &get_real_data() const - { return *move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE internal_type *get_real_data_ptr() - { return move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE const internal_type *get_real_data_ptr() const - { return move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE ~list_node() - { move_detail::force_ptr(this->m_storage.data)->~T(); } - - #if defined(BOOST_CONTAINER_DISABLE_ALIASING_WARNING) - #pragma GCC diagnostic pop - #undef BOOST_CONTAINER_DISABLE_ALIASING_WARNING - # endif - - BOOST_CONTAINER_FORCEINLINE void destroy_header() - { static_cast(this)->~hook_type(); } -}; - -template -struct iiterator_node_value_type< list_node > { typedef T type; }; @@ -136,8 +83,7 @@ struct intrusive_list_type ::template rebind_pointer::type void_pointer; - typedef typename dtl::list_node - node_type; + typedef base_node > node_type; typedef typename dtl::bi::make_list < node_type , dtl::bi::base_hook::type> @@ -184,7 +130,7 @@ class list typedef typename AllocHolder::NodeAlloc NodeAlloc; typedef typename AllocHolder::ValAlloc ValAlloc; typedef typename AllocHolder::Node Node; - typedef dtl::allocator_destroyer Destroyer; + typedef dtl::allocator_node_destroyer Destroyer; typedef typename AllocHolder::alloc_version alloc_version; typedef boost::container::allocator_traits allocator_traits_type; typedef boost::container::equal_to_value @@ -1495,17 +1441,13 @@ class list return iterator(this->icont().insert(p.get(), *tmp)); } - void priv_push_back (const T &x) - { this->insert(this->cend(), x); } + template + void priv_push_back(BOOST_FWD_REF(U) x) + { this->icont().push_back(*this->create_node(::boost::forward(x))); } - void priv_push_back (BOOST_RV_REF(T) x) - { this->insert(this->cend(), boost::move(x)); } - - void priv_push_front (const T &x) - { this->insert(this->cbegin(), x); } - - void priv_push_front (BOOST_RV_REF(T) x) - { this->insert(this->cbegin(), boost::move(x)); } + template + void priv_push_front(BOOST_FWD_REF(U) x) + { this->icont().push_front(*this->create_node(::boost::forward(x))); } class insertion_functor; friend class insertion_functor; diff --git a/include/boost/container/node_handle.hpp b/include/boost/container/node_handle.hpp index 9a39112..8032711 100644 --- a/include/boost/container/node_handle.hpp +++ b/include/boost/container/node_handle.hpp @@ -123,7 +123,7 @@ class node_handle void destroy_deallocate_node() { - nator_traits::destroy(this->node_alloc(), boost::movelib::to_raw_pointer(m_ptr)); + boost::movelib::to_raw_pointer(m_ptr)->destructor(this->node_alloc()); nator_traits::deallocate(this->node_alloc(), m_ptr, 1u); } diff --git a/include/boost/container/slist.hpp b/include/boost/container/slist.hpp index 9e92de1..1adbfba 100644 --- a/include/boost/container/slist.hpp +++ b/include/boost/container/slist.hpp @@ -72,64 +72,9 @@ struct slist_hook , dtl::bi::link_mode >::type type; }; - template -struct slist_node - : public slist_hook::type +struct iiterator_node_value_type< base_node > > { - public: - typedef T value_type; - typedef T internal_type; - typedef typename slist_hook::type hook_type; - - typedef typename dtl::aligned_storage::value>::type storage_t; - storage_t m_storage; - - #if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wstrict-aliasing" - #define BOOST_CONTAINER_DISABLE_ALIASING_WARNING - # endif - - BOOST_CONTAINER_FORCEINLINE T &get_data() - { return *move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE const T &get_data() const - { return *move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE T *get_data_ptr() - { return move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE const T *get_data_ptr() const - { return move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE internal_type &get_real_data() - { return *move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE const internal_type &get_real_data() const - { return *move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE internal_type *get_real_data_ptr() - { return move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE const internal_type *get_real_data_ptr() const - { return move_detail::force_ptr(this->m_storage.data); } - - BOOST_CONTAINER_FORCEINLINE ~slist_node() - { move_detail::force_ptr(this->m_storage.data)->~T(); } - - #if defined(BOOST_CONTAINER_DISABLE_ALIASING_WARNING) - #pragma GCC diagnostic pop - #undef BOOST_CONTAINER_DISABLE_ALIASING_WARNING - # endif - - BOOST_CONTAINER_FORCEINLINE void destroy_header() - { static_cast(this)->~hook_type(); } -}; - - -template -struct iiterator_node_value_type< slist_node > { typedef T type; }; @@ -142,8 +87,7 @@ struct intrusive_slist_type ::template rebind_pointer::type void_pointer; - typedef typename dtl::slist_node - node_type; + typedef base_node > node_type; typedef typename dtl::bi::make_slist Destroyer; + typedef dtl::allocator_node_destroyer Destroyer; typedef typename AllocHolder::alloc_version alloc_version; typedef boost::container:: allocator_traits allocator_traits_type; @@ -249,7 +193,7 @@ class slist ////////////////////////////////////////////// // - // construct/copy/destroy + // constructFr/copy/destroy // ////////////////////////////////////////////// @@ -369,11 +313,12 @@ class slist slist(BOOST_RV_REF(slist) x, const allocator_type &a) : AllocHolder(a) { - if(this->node_alloc() == x.node_alloc()){ - this->icont().swap(x.icont()); + slist & sr = x; + if(this->node_alloc() == sr.node_alloc()){ + this->icont().swap(sr.icont()); } else{ - this->insert_after(this->cbefore_begin(), boost::make_move_iterator(x.begin()), boost::make_move_iterator(x.end())); + this->insert_after(this->cbefore_begin(), boost::make_move_iterator(sr.begin()), boost::make_move_iterator(sr.end())); } } @@ -425,9 +370,10 @@ class slist BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value || allocator_traits_type::is_always_equal::value) { - if (BOOST_LIKELY(this != &x)) { + slist & sr = x; + if (BOOST_LIKELY(this != &sr)) { NodeAlloc &this_alloc = this->node_alloc(); - NodeAlloc &x_alloc = x.node_alloc(); + NodeAlloc &x_alloc = sr.node_alloc(); const bool propagate_alloc = allocator_traits_type:: propagate_on_container_move_assignment::value; const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal; @@ -437,14 +383,14 @@ class slist //Destroy this->clear(); //Move allocator if needed - this->AllocHolder::move_assign_alloc(x); + this->AllocHolder::move_assign_alloc(sr); //Obtain resources - this->icont() = boost::move(x.icont()); + this->icont() = boost::move(sr.icont()); } //Else do a one by one move else{ - this->assign( boost::make_move_iterator(x.begin()) - , boost::make_move_iterator(x.end())); + this->assign( boost::make_move_iterator(sr.begin()) + , boost::make_move_iterator(sr.end())); } } return *this; @@ -1067,7 +1013,7 @@ class slist //! Note: Iterators of values obtained from list x now point to elements of //! this list. Iterators of this list and all the references are not invalidated. void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x) BOOST_NOEXCEPT_OR_NOTHROW - { this->splice_after(prev_p, static_cast(x)); } + { this->splice_after(prev_p, BOOST_MOVE_TO_LV(x)); } //! Requires: prev_p must be a valid iterator of this. //! i must point to an element contained in list x. @@ -1104,7 +1050,7 @@ class slist //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x, const_iterator prev) BOOST_NOEXCEPT_OR_NOTHROW - { this->splice_after(prev_p, static_cast(x), prev); } + { this->splice_after(prev_p, BOOST_MOVE_TO_LV(x), prev); } //! Requires: prev_p must be a valid iterator of this. //! before_first and before_last must be valid iterators of x. @@ -1144,7 +1090,7 @@ class slist //! list. Iterators of this list and all the references are not invalidated. void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x, const_iterator before_first, const_iterator before_last) BOOST_NOEXCEPT_OR_NOTHROW - { this->splice_after(prev_p, static_cast(x), before_first, before_last); } + { this->splice_after(prev_p, BOOST_MOVE_TO_LV(x), before_first, before_last); } //! Requires: prev_p must be a valid iterator of this. //! before_first and before_last must be valid iterators of x. @@ -1188,7 +1134,7 @@ class slist void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x, const_iterator before_first, const_iterator before_last, size_type n) BOOST_NOEXCEPT_OR_NOTHROW - { this->splice_after(prev_p, static_cast(x), before_first, before_last, n); } + { this->splice_after(prev_p, BOOST_MOVE_TO_LV(x), before_first, before_last, n); } //! Effects: Removes all the elements that compare equal to value. //! @@ -1271,7 +1217,7 @@ class slist //! Complexity: This function is linear time: it performs at most //! size() + x.size() - 1 comparisons. void merge(BOOST_RV_REF(slist) x) - { this->merge(static_cast(x)); } + { this->merge(BOOST_MOVE_TO_LV(x)); } //! Requires: p must be a comparison function that induces a strict weak //! ordering and both *this and x must be sorted according to that ordering @@ -1311,7 +1257,7 @@ class slist //! Note: Iterators and references to *this are not invalidated. template void merge(BOOST_RV_REF(slist) x, StrictWeakOrdering comp) - { this->merge(static_cast(x), comp); } + { this->merge(BOOST_MOVE_TO_LV(x), comp); } //! Effects: This function sorts the list *this according to std::less. //! The sort is stable, that is, the relative order of equivalent elements is preserved. @@ -1515,7 +1461,7 @@ class slist //! Note: Iterators of values obtained from list x now point to elements of //! this list. Iterators of this list and all the references are not invalidated. void splice(const_iterator p, BOOST_RV_REF(slist) x) BOOST_NOEXCEPT_OR_NOTHROW - { this->splice(p, static_cast(x)); } + { this->splice(p, BOOST_MOVE_TO_LV(x)); } //! Requires: p must point to an element contained //! by this list. i must point to an element contained in list x. @@ -1549,7 +1495,7 @@ class slist //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator i) BOOST_NOEXCEPT_OR_NOTHROW - { this->splice(p, static_cast(x), i); } + { this->splice(p, BOOST_MOVE_TO_LV(x), i); } //! Requires: p must point to an element contained //! by this list. first and last must point to elements contained in list x. @@ -1583,7 +1529,7 @@ class slist //! Note: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW - { this->splice(p, static_cast(x), first, last); } + { this->splice(p, BOOST_MOVE_TO_LV(x), first, last); } //! Effects: Returns true if x and y are equal //! @@ -1636,11 +1582,9 @@ class slist #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED private: - void priv_push_front (const T &x) - { this->insert_after(this->cbefore_begin(), x); } - - void priv_push_front (BOOST_RV_REF(T) x) - { this->insert_after(this->cbefore_begin(), ::boost::move(x)); } + template + void priv_push_front(BOOST_FWD_REF(U) x) + { this->icont().push_front(*this->create_node(::boost::forward(x))); } bool priv_try_shrink(size_type new_size, const_iterator &last_pos) { diff --git a/test/check_equal_containers.hpp b/test/check_equal_containers.hpp index 8fff4ec..f795b0d 100644 --- a/test/check_equal_containers.hpp +++ b/test/check_equal_containers.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include diff --git a/test/node_handle_test.cpp b/test/node_handle_test.cpp index 3c26379..6aab38e 100644 --- a/test/node_handle_test.cpp +++ b/test/node_handle_test.cpp @@ -140,15 +140,18 @@ struct node ++count; } - ~node() - { - --count; - } + template + void destructor(Alloc &) + { this->~node(); } static unsigned int count; static void reset_count() { count = 0; } + + ~node() + { --count; } + }; template diff --git a/test/set_test.cpp b/test/set_test.cpp index a9c9815..2c7c7ca 100644 --- a/test/set_test.cpp +++ b/test/set_test.cpp @@ -18,6 +18,7 @@ #include "propagate_allocator_test.hpp" #include "emplace_test.hpp" #include "../../intrusive/test/iterator_test.hpp" +#include //for std::pair using namespace boost::container;