Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@101: // (C) Copyright Ion Gaztanaga 2008-2013. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // See http://www.boost.org/libs/container for documentation. Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: #ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP Chris@16: #define BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP Chris@16: Chris@101: #ifndef BOOST_CONFIG_HPP Chris@101: # include Chris@101: #endif Chris@101: Chris@101: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@16: # pragma once Chris@16: #endif Chris@16: Chris@101: #include Chris@16: #include Chris@101: Chris@101: // container Chris@16: #include Chris@101: // container/detail Chris@101: #include Chris@16: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@101: #include Chris@101: #endif Chris@101: // move Chris@101: #include Chris@101: // other Chris@16: #include Chris@101: #include Chris@16: Chris@16: namespace boost { namespace container { namespace container_detail { Chris@16: Chris@101: template Chris@16: struct move_insert_range_proxy Chris@16: { Chris@101: typedef typename allocator_traits::size_type size_type; Chris@101: typedef typename allocator_traits::value_type value_type; Chris@16: Chris@101: explicit move_insert_range_proxy(FwdIt first) Chris@101: : first_(first) Chris@16: {} Chris@16: Chris@101: void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) Chris@16: { Chris@16: this->first_ = ::boost::container::uninitialized_move_alloc_n_source Chris@101: (a, this->first_, n, p); Chris@16: } Chris@16: Chris@101: void copy_n_and_update(Allocator &, Iterator p, size_type n) Chris@16: { Chris@16: this->first_ = ::boost::container::move_n_source(this->first_, n, p); Chris@16: } Chris@16: Chris@16: FwdIt first_; Chris@16: }; Chris@16: Chris@16: Chris@101: template Chris@16: struct insert_range_proxy Chris@16: { Chris@101: typedef typename allocator_traits::size_type size_type; Chris@101: typedef typename allocator_traits::value_type value_type; Chris@16: Chris@101: explicit insert_range_proxy(FwdIt first) Chris@101: : first_(first) Chris@16: {} Chris@16: Chris@101: void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) Chris@16: { Chris@101: this->first_ = ::boost::container::uninitialized_copy_alloc_n_source(a, this->first_, n, p); Chris@16: } Chris@16: Chris@101: void copy_n_and_update(Allocator &, Iterator p, size_type n) Chris@16: { Chris@16: this->first_ = ::boost::container::copy_n_source(this->first_, n, p); Chris@16: } Chris@16: Chris@16: FwdIt first_; Chris@16: }; Chris@16: Chris@16: Chris@101: template Chris@16: struct insert_n_copies_proxy Chris@16: { Chris@101: typedef typename allocator_traits::size_type size_type; Chris@101: typedef typename allocator_traits::value_type value_type; Chris@16: Chris@101: explicit insert_n_copies_proxy(const value_type &v) Chris@101: : v_(v) Chris@16: {} Chris@16: Chris@101: void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const Chris@101: { boost::container::uninitialized_fill_alloc_n(a, v_, n, p); } Chris@16: Chris@101: void copy_n_and_update(Allocator &, Iterator p, size_type n) const Chris@101: { Chris@101: for (; 0 < n; --n, ++p){ Chris@101: *p = v_; Chris@101: } Chris@101: } Chris@16: Chris@16: const value_type &v_; Chris@16: }; Chris@16: Chris@101: template Chris@16: struct insert_value_initialized_n_proxy Chris@16: { Chris@101: typedef ::boost::container::allocator_traits alloc_traits; Chris@101: typedef typename allocator_traits::size_type size_type; Chris@101: typedef typename allocator_traits::value_type value_type; Chris@16: Chris@101: void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const Chris@101: { boost::container::uninitialized_value_init_alloc_n(a, n, p); } Chris@16: Chris@101: void copy_n_and_update(Allocator &, Iterator, size_type) const Chris@101: { BOOST_ASSERT(false); } Chris@16: }; Chris@16: Chris@101: template Chris@16: struct insert_default_initialized_n_proxy Chris@16: { Chris@101: typedef ::boost::container::allocator_traits alloc_traits; Chris@101: typedef typename allocator_traits::size_type size_type; Chris@101: typedef typename allocator_traits::value_type value_type; Chris@16: Chris@101: void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const Chris@101: { boost::container::uninitialized_default_init_alloc_n(a, n, p); } Chris@16: Chris@101: void copy_n_and_update(Allocator &, Iterator, size_type) const Chris@101: { BOOST_ASSERT(false); } Chris@16: }; Chris@16: Chris@101: template Chris@16: struct insert_copy_proxy Chris@16: { Chris@101: typedef boost::container::allocator_traits alloc_traits; Chris@16: typedef typename alloc_traits::size_type size_type; Chris@16: typedef typename alloc_traits::value_type value_type; Chris@16: Chris@101: explicit insert_copy_proxy(const value_type &v) Chris@101: : v_(v) Chris@16: {} Chris@16: Chris@101: void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const Chris@16: { Chris@16: BOOST_ASSERT(n == 1); (void)n; Chris@101: alloc_traits::construct( a, iterator_to_raw_pointer(p), v_); Chris@16: } Chris@16: Chris@101: void copy_n_and_update(Allocator &, Iterator p, size_type n) const Chris@16: { Chris@16: BOOST_ASSERT(n == 1); (void)n; Chris@16: *p =v_; Chris@16: } Chris@16: Chris@16: const value_type &v_; Chris@16: }; Chris@16: Chris@16: Chris@101: template Chris@16: struct insert_move_proxy Chris@16: { Chris@101: typedef boost::container::allocator_traits alloc_traits; Chris@16: typedef typename alloc_traits::size_type size_type; Chris@16: typedef typename alloc_traits::value_type value_type; Chris@16: Chris@101: explicit insert_move_proxy(value_type &v) Chris@101: : v_(v) Chris@16: {} Chris@16: Chris@101: void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const Chris@16: { Chris@16: BOOST_ASSERT(n == 1); (void)n; Chris@101: alloc_traits::construct( a, iterator_to_raw_pointer(p), ::boost::move(v_) ); Chris@16: } Chris@16: Chris@101: void copy_n_and_update(Allocator &, Iterator p, size_type n) const Chris@16: { Chris@16: BOOST_ASSERT(n == 1); (void)n; Chris@16: *p = ::boost::move(v_); Chris@16: } Chris@16: Chris@16: value_type &v_; Chris@16: }; Chris@16: Chris@101: template Chris@101: insert_move_proxy get_insert_value_proxy(BOOST_RV_REF(typename boost::container::iterator_traits::value_type) v) Chris@16: { Chris@101: return insert_move_proxy(v); Chris@16: } Chris@16: Chris@101: template Chris@101: insert_copy_proxy get_insert_value_proxy(const typename boost::container::iterator_traits::value_type &v) Chris@16: { Chris@101: return insert_copy_proxy(v); Chris@16: } Chris@16: Chris@16: }}} //namespace boost { namespace container { namespace container_detail { Chris@16: Chris@101: #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@16: #include Chris@101: #include Chris@16: Chris@16: namespace boost { Chris@16: namespace container { Chris@16: namespace container_detail { Chris@16: Chris@101: template Chris@101: struct insert_nonmovable_emplace_proxy Chris@16: { Chris@101: typedef boost::container::allocator_traits alloc_traits; Chris@16: typedef typename alloc_traits::size_type size_type; Chris@16: typedef typename alloc_traits::value_type value_type; Chris@16: Chris@16: typedef typename build_number_seq::type index_tuple_t; Chris@16: Chris@101: explicit insert_nonmovable_emplace_proxy(BOOST_FWD_REF(Args)... args) Chris@101: : args_(args...) Chris@16: {} Chris@16: Chris@101: void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) Chris@101: { this->priv_uninitialized_copy_some_and_update(a, index_tuple_t(), p, n); } Chris@16: Chris@16: private: Chris@16: template Chris@101: void priv_uninitialized_copy_some_and_update(Allocator &a, const index_tuple&, Iterator p, size_type n) Chris@16: { Chris@16: BOOST_ASSERT(n == 1); (void)n; Chris@101: alloc_traits::construct( a, iterator_to_raw_pointer(p), ::boost::forward(get(this->args_))... ); Chris@16: } Chris@16: Chris@16: protected: Chris@16: tuple args_; Chris@16: }; Chris@16: Chris@101: template Chris@16: struct insert_emplace_proxy Chris@101: : public insert_nonmovable_emplace_proxy Chris@16: { Chris@101: typedef insert_nonmovable_emplace_proxy base_t; Chris@101: typedef boost::container::allocator_traits alloc_traits; Chris@16: typedef typename base_t::value_type value_type; Chris@16: typedef typename base_t::size_type size_type; Chris@16: typedef typename base_t::index_tuple_t index_tuple_t; Chris@16: Chris@101: explicit insert_emplace_proxy(BOOST_FWD_REF(Args)... args) Chris@101: : base_t(::boost::forward(args)...) Chris@16: {} Chris@16: Chris@101: void copy_n_and_update(Allocator &a, Iterator p, size_type n) Chris@101: { this->priv_copy_some_and_update(a, index_tuple_t(), p, n); } Chris@16: Chris@16: private: Chris@16: Chris@16: template Chris@101: void priv_copy_some_and_update(Allocator &a, const index_tuple&, Iterator p, size_type n) Chris@16: { Chris@16: BOOST_ASSERT(n ==1); (void)n; Chris@101: typename aligned_storage::value>::type v; Chris@16: value_type *vp = static_cast(static_cast(&v)); Chris@101: alloc_traits::construct(a, vp, Chris@16: ::boost::forward(get(this->args_))...); Chris@16: BOOST_TRY{ Chris@16: *p = ::boost::move(*vp); Chris@16: } Chris@16: BOOST_CATCH(...){ Chris@101: alloc_traits::destroy(a, vp); Chris@16: BOOST_RETHROW Chris@16: } Chris@16: BOOST_CATCH_END Chris@101: alloc_traits::destroy(a, vp); Chris@16: } Chris@16: }; Chris@16: Chris@101: //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type Chris@101: template Chris@101: struct insert_emplace_proxy::value_type> Chris@101: : public insert_move_proxy Chris@101: { Chris@101: explicit insert_emplace_proxy(typename boost::container::allocator_traits::value_type &&v) Chris@101: : insert_move_proxy(v) Chris@101: {} Chris@101: }; Chris@101: Chris@101: //We use "add_const" here as adding "const" only confuses MSVC12(and maybe later) provoking Chris@101: //compiler error C2752 ("more than one partial specialization matches"). Chris@101: //Any problem is solvable with an extra layer of indirection? ;-) Chris@101: template Chris@101: struct insert_emplace_proxy::value_type>::type Chris@101: > Chris@101: : public insert_copy_proxy Chris@101: { Chris@101: explicit insert_emplace_proxy(const typename boost::container::allocator_traits::value_type &v) Chris@101: : insert_copy_proxy(v) Chris@101: {} Chris@101: }; Chris@101: Chris@101: template Chris@101: struct insert_emplace_proxy::value_type &> Chris@101: : public insert_copy_proxy Chris@101: { Chris@101: explicit insert_emplace_proxy(const typename boost::container::allocator_traits::value_type &v) Chris@101: : insert_copy_proxy(v) Chris@101: {} Chris@101: }; Chris@101: Chris@101: template Chris@101: struct insert_emplace_proxy::value_type>::type & Chris@101: > Chris@101: : public insert_copy_proxy Chris@101: { Chris@101: explicit insert_emplace_proxy(const typename boost::container::allocator_traits::value_type &v) Chris@101: : insert_copy_proxy(v) Chris@101: {} Chris@101: }; Chris@101: Chris@16: }}} //namespace boost { namespace container { namespace container_detail { Chris@16: Chris@101: #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: namespace container { Chris@16: namespace container_detail { Chris@16: Chris@101: #define BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE(N) \ Chris@101: template< class Allocator, class Iterator BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\ Chris@101: struct insert_nonmovable_emplace_proxy##N\ Chris@101: {\ Chris@101: typedef boost::container::allocator_traits alloc_traits;\ Chris@101: typedef typename alloc_traits::size_type size_type;\ Chris@101: typedef typename alloc_traits::value_type value_type;\ Chris@101: \ Chris@101: explicit insert_nonmovable_emplace_proxy##N(BOOST_MOVE_UREF##N)\ Chris@101: BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N {}\ Chris@101: \ Chris@101: void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)\ Chris@101: {\ Chris@101: BOOST_ASSERT(n == 1); (void)n;\ Chris@101: alloc_traits::construct(a, iterator_to_raw_pointer(p) BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\ Chris@101: }\ Chris@101: \ Chris@101: void copy_n_and_update(Allocator &, Iterator, size_type)\ Chris@101: { BOOST_ASSERT(false); }\ Chris@101: \ Chris@101: protected:\ Chris@101: BOOST_MOVE_MREF##N\ Chris@101: };\ Chris@101: \ Chris@101: template< class Allocator, class Iterator BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\ Chris@101: struct insert_emplace_proxy_arg##N\ Chris@101: : insert_nonmovable_emplace_proxy##N< Allocator, Iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N >\ Chris@101: {\ Chris@101: typedef insert_nonmovable_emplace_proxy##N\ Chris@101: < Allocator, Iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N > base_t;\ Chris@101: typedef typename base_t::value_type value_type;\ Chris@101: typedef typename base_t::size_type size_type;\ Chris@101: typedef boost::container::allocator_traits alloc_traits;\ Chris@101: \ Chris@101: explicit insert_emplace_proxy_arg##N(BOOST_MOVE_UREF##N)\ Chris@101: : base_t(BOOST_MOVE_FWD##N){}\ Chris@101: \ Chris@101: void copy_n_and_update(Allocator &a, Iterator p, size_type n)\ Chris@101: {\ Chris@101: BOOST_ASSERT(n == 1); (void)n;\ Chris@101: typename aligned_storage::value>::type v;\ Chris@101: BOOST_ASSERT((((size_type)(&v)) % alignment_of::value) == 0);\ Chris@101: value_type *vp = static_cast(static_cast(&v));\ Chris@101: alloc_traits::construct(a, vp BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\ Chris@101: BOOST_TRY{\ Chris@101: *p = ::boost::move(*vp);\ Chris@101: }\ Chris@101: BOOST_CATCH(...){\ Chris@101: alloc_traits::destroy(a, vp);\ Chris@101: BOOST_RETHROW\ Chris@101: }\ Chris@101: BOOST_CATCH_END\ Chris@101: alloc_traits::destroy(a, vp);\ Chris@101: }\ Chris@101: };\ Chris@101: // Chris@101: BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE) Chris@101: #undef BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE Chris@101: Chris@101: #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@101: Chris@101: //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type Chris@101: template Chris@101: struct insert_emplace_proxy_arg1::value_type> > Chris@101: : public insert_move_proxy Chris@101: { Chris@101: explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits::value_type &v) Chris@101: : insert_move_proxy(v) Chris@101: {} Chris@101: }; Chris@101: Chris@101: template Chris@101: struct insert_emplace_proxy_arg1::value_type> Chris@101: : public insert_copy_proxy Chris@101: { Chris@101: explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits::value_type &v) Chris@101: : insert_copy_proxy(v) Chris@101: {} Chris@101: }; Chris@101: Chris@101: #else //e.g. MSVC10 & MSVC11 Chris@101: Chris@101: //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type Chris@101: template Chris@101: struct insert_emplace_proxy_arg1::value_type> Chris@101: : public insert_move_proxy Chris@101: { Chris@101: explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits::value_type &&v) Chris@101: : insert_move_proxy(v) Chris@101: {} Chris@101: }; Chris@101: Chris@101: //We use "add_const" here as adding "const" only confuses MSVC10&11 provoking Chris@101: //compiler error C2752 ("more than one partial specialization matches"). Chris@101: //Any problem is solvable with an extra layer of indirection? ;-) Chris@101: template Chris@101: struct insert_emplace_proxy_arg1::value_type>::type Chris@101: > Chris@101: : public insert_copy_proxy Chris@101: { Chris@101: explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits::value_type &v) Chris@101: : insert_copy_proxy(v) Chris@101: {} Chris@101: }; Chris@101: Chris@101: template Chris@101: struct insert_emplace_proxy_arg1::value_type &> Chris@101: : public insert_copy_proxy Chris@101: { Chris@101: explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits::value_type &v) Chris@101: : insert_copy_proxy(v) Chris@101: {} Chris@101: }; Chris@101: Chris@101: template Chris@101: struct insert_emplace_proxy_arg1::value_type>::type & Chris@101: > Chris@101: : public insert_copy_proxy Chris@101: { Chris@101: explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits::value_type &v) Chris@101: : insert_copy_proxy(v) Chris@101: {} Chris@101: }; Chris@101: Chris@101: #endif Chris@16: Chris@16: }}} //namespace boost { namespace container { namespace container_detail { Chris@16: Chris@101: #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@16: #include Chris@16: Chris@16: #endif //#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP