1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost 4 // Software License, Version 1.0. (See accompanying file 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 // See http://www.boost.org/libs/container for documentation. 8 // 9 ////////////////////////////////////////////////////////////////////////////// 10 11 #ifndef BOOST_CONTAINER_CONTAINER_SMALL_VECTOR_HPP 12 #define BOOST_CONTAINER_CONTAINER_SMALL_VECTOR_HPP 13 14 #ifndef BOOST_CONFIG_HPP 15 # include <boost/config.hpp> 16 #endif 17 18 #if defined(BOOST_HAS_PRAGMA_ONCE) 19 # pragma once 20 #endif 21 22 #include <boost/container/detail/config_begin.hpp> 23 #include <boost/container/detail/workaround.hpp> 24 25 // container 26 #include <boost/container/container_fwd.hpp> 27 #include <boost/container/vector.hpp> 28 #include <boost/container/allocator_traits.hpp> 29 #include <boost/container/new_allocator.hpp> //new_allocator 30 // container/detail 31 #include <boost/container/detail/type_traits.hpp> 32 #include <boost/container/detail/version_type.hpp> 33 34 //move 35 #include <boost/move/adl_move_swap.hpp> 36 #include <boost/move/iterator.hpp> 37 38 //move/detail 39 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 40 #include <boost/move/detail/fwd_macros.hpp> 41 #endif 42 43 //std 44 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) 45 #include <initializer_list> //for std::initializer_list 46 #endif 47 48 namespace boost { 49 namespace container { 50 51 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 52 53 template <class T, class Allocator = new_allocator<T> > 54 class small_vector_base; 55 56 #endif 57 58 //! A non-standard allocator used to implement `small_vector`. 59 //! Users should never use it directly. It is described here 60 //! for documentation purposes. 61 //! 62 //! This allocator inherits from a standard-conforming allocator 63 //! and forwards member functions to the standard allocator except 64 //! when internal storage is being used as memory source. 65 //! 66 //! This allocator is a "partially_propagable" allocator and 67 //! defines `is_partially_propagable` as true_type. 68 //! 69 //! A partially propagable allocator means that not all storage 70 //! allocatod by an instance of `small_vector_allocator` can be 71 //! deallocated by another instance of this type, even if both 72 //! instances compare equal or an instance is propagated to another 73 //! one using the copy/move constructor or assignment. The storage that 74 //! can never be propagated is identified by `storage_is_unpropagable(p)`. 75 //! 76 //! `boost::container::vector` supports partially propagable allocators 77 //! fallbacking to deep copy/swap/move operations when internal storage 78 //! is being used to store vector elements. 79 //! 80 //! `small_vector_allocator` assumes that will be instantiated as 81 //! `boost::container::vector< T, small_vector_allocator<Allocator> >` 82 //! and internal storage can be obtained downcasting that vector 83 //! to `small_vector_base<T>`. 84 template<class Allocator> 85 class small_vector_allocator 86 : public Allocator 87 { 88 typedef unsigned int allocation_type; 89 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 90 private: 91 BOOST_COPYABLE_AND_MOVABLE(small_vector_allocator) const92 BOOST_COPYABLE_AND_MOVABLE(small_vector_allocator) 93 94 const Allocator &as_base() const 95 { return static_cast<const Allocator&>(*this); } 96 as_base()97 Allocator &as_base() 98 { return static_cast<Allocator&>(*this); } 99 100 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 101 102 public: 103 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 104 typedef allocator_traits<Allocator> allocator_traits_type; 105 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 106 107 typedef typename allocator_traits<Allocator>::value_type value_type; 108 typedef typename allocator_traits<Allocator>::pointer pointer; 109 typedef typename allocator_traits<Allocator>::const_pointer const_pointer; 110 typedef typename allocator_traits<Allocator>::reference reference; 111 typedef typename allocator_traits<Allocator>::const_reference const_reference; 112 typedef typename allocator_traits<Allocator>::size_type size_type; 113 typedef typename allocator_traits<Allocator>::difference_type difference_type; 114 typedef typename allocator_traits<Allocator>::void_pointer void_pointer; 115 typedef typename allocator_traits<Allocator>::const_void_pointer const_void_pointer; 116 117 typedef typename allocator_traits<Allocator>::propagate_on_container_copy_assignment propagate_on_container_copy_assignment; 118 typedef typename allocator_traits<Allocator>::propagate_on_container_move_assignment propagate_on_container_move_assignment; 119 typedef typename allocator_traits<Allocator>::propagate_on_container_swap propagate_on_container_swap; 120 //! An integral constant with member `::value == false` 121 typedef BOOST_CONTAINER_IMPDEF(container_detail::bool_<false>) is_always_equal; 122 //! An integral constant with member `::value == true` 123 typedef BOOST_CONTAINER_IMPDEF(container_detail::bool_<true>) is_partially_propagable; 124 125 BOOST_CONTAINER_DOCIGN(typedef container_detail::version_type<small_vector_allocator BOOST_CONTAINER_I 1> version;) 126 127 //!Obtains an small_vector_allocator that allocates 128 //!objects of type T2 129 template<class T2> 130 struct rebind 131 { 132 typedef typename allocator_traits<Allocator>::template rebind_alloc<T2>::type other; 133 }; 134 135 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) 136 //!Constructor from arbitrary arguments 137 template<class ...Args> small_vector_allocator(BOOST_FWD_REF (Args)...args)138 explicit small_vector_allocator(BOOST_FWD_REF(Args) ...args) 139 : Allocator(::boost::forward<Args>(args)...) 140 {} 141 #else 142 #define BOOST_CONTAINER_SMALL_VECTOR_ALLOCATOR_CTOR_CODE(N) \ 143 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ 144 explicit small_vector_allocator(BOOST_MOVE_UREF##N)\ 145 : Allocator(BOOST_MOVE_FWD##N)\ 146 {}\ 147 // 148 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SMALL_VECTOR_ALLOCATOR_CTOR_CODE) 149 #undef BOOST_CONTAINER_SMALL_VECTOR_ALLOCATOR_CTOR_CODE 150 #endif 151 152 //!Constructor from other small_vector_allocator. 153 //!Never throws small_vector_allocator(const small_vector_allocator & other)154 small_vector_allocator(const small_vector_allocator &other) BOOST_NOEXCEPT_OR_NOTHROW 155 : Allocator(other.as_base()) 156 {} 157 158 //!Move constructor from small_vector_allocator. 159 //!Never throws small_vector_allocator(BOOST_RV_REF (small_vector_allocator)other)160 small_vector_allocator(BOOST_RV_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW 161 : Allocator(::boost::move(other.as_base())) 162 {} 163 164 //!Constructor from related small_vector_allocator. 165 //!Never throws 166 template<class OtherAllocator> small_vector_allocator(const small_vector_allocator<OtherAllocator> & other)167 small_vector_allocator(const small_vector_allocator<OtherAllocator> &other) BOOST_NOEXCEPT_OR_NOTHROW 168 : Allocator(other.as_base()) 169 {} 170 171 //!Move constructor from related small_vector_allocator. 172 //!Never throws 173 template<class OtherAllocator> small_vector_allocator(BOOST_RV_REF (small_vector_allocator<OtherAllocator>)other)174 small_vector_allocator(BOOST_RV_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW 175 : Allocator(::boost::move(other.as_base())) 176 {} 177 178 //!Assignment from other small_vector_allocator. 179 //!Never throws operator =(BOOST_COPY_ASSIGN_REF (small_vector_allocator)other)180 small_vector_allocator & operator=(BOOST_COPY_ASSIGN_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW 181 { return static_cast<small_vector_allocator&>(this->Allocator::operator=(other.as_base())); } 182 183 //!Move constructor from other small_vector_allocator. 184 //!Never throws operator =(BOOST_RV_REF (small_vector_allocator)other)185 small_vector_allocator & operator=(BOOST_RV_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW 186 { return static_cast<small_vector_allocator&>(this->Allocator::operator=(::boost::move(other.as_base()))); } 187 188 //!Assignment from related small_vector_allocator. 189 //!Never throws 190 template<class OtherAllocator> operator =(BOOST_COPY_ASSIGN_REF (small_vector_allocator<OtherAllocator>)other)191 small_vector_allocator & operator=(BOOST_COPY_ASSIGN_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW 192 { return static_cast<small_vector_allocator&>(this->Allocator::operator=(other.as_base())); } 193 194 //!Move assignment from related small_vector_allocator. 195 //!Never throws 196 template<class OtherAllocator> operator =(BOOST_RV_REF (small_vector_allocator<OtherAllocator>)other)197 small_vector_allocator & operator=(BOOST_RV_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW 198 { return static_cast<small_vector_allocator&>(this->Allocator::operator=(::boost::move(other.as_base()))); } 199 200 //!Allocates storage from the standard-conforming allocator allocate(size_type count,const_void_pointer hint=const_void_pointer ())201 pointer allocate(size_type count, const_void_pointer hint = const_void_pointer()) 202 { return allocator_traits_type::allocate(this->as_base(), count, hint); } 203 204 //!Deallocates previously allocated memory. 205 //!Never throws deallocate(pointer ptr,size_type n)206 void deallocate(pointer ptr, size_type n) BOOST_NOEXCEPT_OR_NOTHROW 207 { 208 if(!this->is_internal_storage(ptr)) 209 allocator_traits_type::deallocate(this->as_base(), ptr, n); 210 } 211 212 //!Returns the maximum number of elements that could be allocated. 213 //!Never throws max_size() const214 size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW 215 { return allocator_traits_type::max_size(this->as_base()); } 216 select_on_container_copy_construction() const217 small_vector_allocator select_on_container_copy_construction() const 218 { return small_vector_allocator(allocator_traits_type::select_on_container_copy_construction(this->as_base())); } 219 storage_is_unpropagable(pointer p) const220 bool storage_is_unpropagable(pointer p) const 221 { return this->is_internal_storage(p) || allocator_traits_type::storage_is_unpropagable(this->as_base(), p); } 222 223 //!Swaps two allocators, does nothing 224 //!because this small_vector_allocator is stateless swap(small_vector_allocator & l,small_vector_allocator & r)225 friend void swap(small_vector_allocator &l, small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW 226 { boost::adl_move_swap(l.as_base(), r.as_base()); } 227 228 //!An small_vector_allocator always compares to true, as memory allocated with one 229 //!instance can be deallocated by another instance (except for unpropagable storage) operator ==(const small_vector_allocator & l,const small_vector_allocator & r)230 friend bool operator==(const small_vector_allocator &l, const small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW 231 { return allocator_traits_type::equal(l.as_base(), r.as_base()); } 232 233 //!An small_vector_allocator always compares to false, as memory allocated with one 234 //!instance can be deallocated by another instance operator !=(const small_vector_allocator & l,const small_vector_allocator & r)235 friend bool operator!=(const small_vector_allocator &l, const small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW 236 { return !(l == r); } 237 238 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 239 /* 240 //!An advanced function that offers in-place expansion shrink to fit and new allocation 241 //!capabilities. Memory allocated with this function can only be deallocated with deallocate() 242 //!or deallocate_many(). 243 //!This function is available only with Version == 2 244 pointer allocation_command(allocation_type command, 245 size_type limit_size, 246 size_type &prefer_in_recvd_out_size, 247 pointer &reuse) 248 { return allocator_traits_type::allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); } 249 250 //!Returns maximum the number of objects the previously allocated memory 251 //!pointed by p can hold. 252 //!Memory must not have been allocated with 253 //!allocate_one or allocate_individual. 254 //!This function is available only with Version == 2 255 size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW 256 { return allocator_traits_type::size(p); } 257 */ 258 private: 259 /* 260 //!Allocates just one object. Memory allocated with this function 261 //!must be deallocated only with deallocate_one(). 262 //!Throws bad_alloc if there is no enough memory 263 //!This function is available only with Version == 2 264 using Allocator::allocate_one; 265 using Allocator::allocate_individual; 266 using Allocator::deallocate_one; 267 using Allocator::deallocate_individual; 268 using Allocator::allocate_many; 269 using Allocator::deallocate_many;*/ 270 is_internal_storage(pointer p) const271 bool is_internal_storage(pointer p) const 272 { return this->internal_storage() == p; } 273 internal_storage() const274 pointer internal_storage() const 275 { 276 typedef typename Allocator::value_type value_type; 277 typedef container_detail::vector_alloc_holder< small_vector_allocator<Allocator> > vector_alloc_holder_t; 278 typedef vector<value_type, small_vector_allocator<Allocator> > vector_base; 279 typedef small_vector_base<value_type, Allocator> derived_type; 280 // 281 const vector_alloc_holder_t &v_holder = static_cast<const vector_alloc_holder_t &>(*this); 282 const vector_base &v_base = reinterpret_cast<const vector_base &>(v_holder); 283 const derived_type &d_base = static_cast<const derived_type &>(v_base); 284 return d_base.internal_storage(); 285 } 286 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 287 }; 288 289 //! This class consists of common code from all small_vector<T, N> types that don't depend on the 290 //! "N" template parameter. This class is non-copyable and non-destructible, so this class tipically 291 //! used as reference argument to functions that read or write small vectors. Since `small_vector<T, N>` 292 //! derives from `small_vector_base<T>`, the conversion to `small_vector_base` is implicit: 293 //! <code> 294 //! 295 //! //Clients can pass any small_vector<Foo, N>. 296 //! void read_any_small_vector_of_foo(const small_vector_base<Foo> &in_parameter); 297 //! void modify_any_small_vector_of_foo(small_vector_base<Foo> &out_parameter); 298 //! 299 //! void some_function() 300 //! { 301 //! small_vector<Foo, 8> myvector; 302 //! read_any_small_vector_of_foo(myvector); // Reads myvector 303 //! modify_any_small_vector_of_foo(myvector); // Modifies myvector 304 //! } 305 //! </code> 306 //! 307 //! All `boost::container:vector` member functions are inherited. See `vector` documentation for details. 308 //! 309 template <class T, class SecondaryAllocator> 310 class small_vector_base 311 : public vector<T, small_vector_allocator<SecondaryAllocator> > 312 { 313 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 314 public: 315 //Make it public as it will be inherited by small_vector and container 316 //must have this public member 317 typedef typename allocator_traits<SecondaryAllocator>::pointer pointer; 318 319 private: 320 BOOST_COPYABLE_AND_MOVABLE(small_vector_base) 321 322 friend class small_vector_allocator<SecondaryAllocator>; 323 internal_storage() const324 pointer internal_storage() const BOOST_NOEXCEPT_OR_NOTHROW 325 { 326 return boost::intrusive::pointer_traits<pointer>::pointer_to 327 (*const_cast<T*>(static_cast<const T*>(static_cast<const void*>(&m_storage_start)))); 328 } 329 330 typedef vector<T, small_vector_allocator<SecondaryAllocator> > base_type; as_base()331 base_type &as_base() { return static_cast<base_type&>(*this); } as_base() const332 const base_type &as_base() const { return static_cast<const base_type&>(*this); } 333 334 public: 335 typedef typename container_detail::aligned_storage 336 <sizeof(T), container_detail::alignment_of<T>::value>::type storage_type; 337 typedef small_vector_allocator<SecondaryAllocator> allocator_type; 338 339 protected: 340 typedef typename base_type::initial_capacity_t initial_capacity_t; 341 small_vector_base(initial_capacity_t,std::size_t initial_capacity)342 explicit small_vector_base(initial_capacity_t, std::size_t initial_capacity) 343 : base_type(initial_capacity_t(), this->internal_storage(), initial_capacity) 344 {} 345 346 template<class AllocFwd> small_vector_base(initial_capacity_t,std::size_t capacity,BOOST_FWD_REF (AllocFwd)a)347 explicit small_vector_base(initial_capacity_t, std::size_t capacity, BOOST_FWD_REF(AllocFwd) a) 348 : base_type(initial_capacity_t(), this->internal_storage(), capacity, ::boost::forward<AllocFwd>(a)) 349 {} 350 ~small_vector_base()351 ~small_vector_base(){} 352 353 using base_type::is_propagable_from; 354 using base_type::steal_resources; 355 356 private: 357 //The only member 358 storage_type m_storage_start; 359 360 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 361 362 public: operator =(BOOST_COPY_ASSIGN_REF (small_vector_base)other)363 small_vector_base& operator=(BOOST_COPY_ASSIGN_REF(small_vector_base) other) 364 { return static_cast<small_vector_base&>(this->base_type::operator=(static_cast<base_type const&>(other))); } 365 operator =(BOOST_RV_REF (small_vector_base)other)366 small_vector_base& operator=(BOOST_RV_REF(small_vector_base) other) 367 { return static_cast<small_vector_base&>(this->base_type::operator=(BOOST_MOVE_BASE(base_type, other))); } 368 swap(small_vector_base & other)369 void swap(small_vector_base &other) 370 { return this->base_type::swap(other); } 371 }; 372 373 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 374 375 ///////////////////////////////////////////////////// 376 // 377 // small_vector_storage_calculator 378 // 379 ///////////////////////////////////////////////////// 380 template<std::size_t Needed, std::size_t Hdr, std::size_t SSize, bool NeedsZero = (0u == Needed || Needed <= Hdr)> 381 struct small_vector_storage_calculator_helper 382 { 383 static const std::size_t value = (Needed - Hdr - 1u)/SSize + 1u; 384 }; 385 386 template<std::size_t Needed, std::size_t Hdr, std::size_t SSize> 387 struct small_vector_storage_calculator_helper<Needed, Hdr, SSize, true> 388 { 389 static const std::size_t value = 0u; 390 }; 391 392 template<class Storage, class Allocator, class T, std::size_t N> 393 struct small_vector_storage_calculator 394 { 395 typedef small_vector_base<T, Allocator> svh_type; 396 typedef vector<T, small_vector_allocator<Allocator> > svhb_type; 397 static const std::size_t s_align = container_detail::alignment_of<Storage>::value; 398 static const std::size_t s_size = sizeof(Storage); 399 static const std::size_t svh_sizeof = sizeof(svh_type); 400 static const std::size_t svhb_sizeof = sizeof(svhb_type); 401 static const std::size_t s_start = ((svhb_sizeof-1)/s_align+1)*s_align; 402 static const std::size_t header_bytes = svh_sizeof-s_start; 403 static const std::size_t needed_bytes = sizeof(T)*N; 404 static const std::size_t needed_extra_storages = 405 small_vector_storage_calculator_helper<needed_bytes, header_bytes, s_size>::value; 406 }; 407 408 ///////////////////////////////////////////////////// 409 // 410 // small_vector_storage_definer 411 // 412 ///////////////////////////////////////////////////// 413 template<class Storage, std::size_t N> 414 struct small_vector_storage 415 { 416 Storage m_rest_of_storage[N]; 417 }; 418 419 template<class Storage> 420 struct small_vector_storage<Storage, 0> 421 {}; 422 423 template<class Allocator, std::size_t N> 424 struct small_vector_storage_definer 425 { 426 typedef typename Allocator::value_type value_type; 427 typedef typename small_vector_base<value_type, Allocator>::storage_type storage_type; 428 static const std::size_t needed_extra_storages = 429 small_vector_storage_calculator<storage_type, Allocator, value_type, N>::needed_extra_storages; 430 typedef small_vector_storage<storage_type, needed_extra_storages> type; 431 }; 432 433 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 434 435 //! small_vector is a vector-like container optimized for the case when it contains few elements. 436 //! It contains some preallocated elements in-place, which can avoid the use of dynamic storage allocation 437 //! when the actual number of elements is below that preallocated threshold. 438 //! 439 //! `small_vector<T, N, Allocator>` is convertible to `small_vector_base<T, Allocator>` that is independent 440 //! from the preallocated element capacity, so client code does not need to be templated on that N argument. 441 //! 442 //! All `boost::container::vector` member functions are inherited. See `vector` documentation for details. 443 //! 444 //! \tparam T The type of object that is stored in the small_vector 445 //! \tparam N The number of preallocated elements stored inside small_vector. It shall be less than Allocator::max_size(); 446 //! \tparam Allocator The allocator used for memory management when the number of elements exceeds N. 447 template <class T, std::size_t N, class Allocator BOOST_CONTAINER_DOCONLY(= new_allocator<T>) > 448 class small_vector : public small_vector_base<T, Allocator> 449 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 450 , private small_vector_storage_definer<Allocator, N>::type 451 #endif 452 { 453 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 454 typedef small_vector_base<T, Allocator> base_type; 455 typedef typename small_vector_storage_definer<Allocator, N>::type remaining_storage_holder; 456 457 BOOST_COPYABLE_AND_MOVABLE(small_vector) 458 459 typedef typename base_type::initial_capacity_t initial_capacity_t; 460 typedef allocator_traits<typename base_type::allocator_type> allocator_traits_type; 461 462 public: 463 typedef small_vector_storage_calculator< typename small_vector_base<T, Allocator> 464 ::storage_type, Allocator, T, N> storage_test; 465 466 static const std::size_t needed_extra_storages = storage_test::needed_extra_storages; 467 static const std::size_t needed_bytes = storage_test::needed_bytes; 468 static const std::size_t header_bytes = storage_test::header_bytes; 469 static const std::size_t s_start = storage_test::s_start; 470 471 typedef typename base_type::allocator_type allocator_type; 472 typedef typename base_type::size_type size_type; 473 typedef typename base_type::value_type value_type; 474 internal_capacity()475 static std::size_t internal_capacity() 476 { return (sizeof(small_vector) - storage_test::s_start)/sizeof(T); } 477 478 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 479 480 public: small_vector()481 small_vector() 482 : base_type(initial_capacity_t(), internal_capacity()) 483 {} 484 small_vector(size_type n)485 explicit small_vector(size_type n) 486 : base_type(initial_capacity_t(), internal_capacity()) 487 { this->resize(n); } 488 small_vector(const allocator_type & a)489 explicit small_vector(const allocator_type &a) 490 : base_type(initial_capacity_t(), internal_capacity(), a) 491 {} 492 small_vector(size_type n,const allocator_type & a)493 small_vector(size_type n, const allocator_type &a) 494 : base_type(initial_capacity_t(), internal_capacity(), a) 495 { this->resize(n); } 496 small_vector(const small_vector & other)497 small_vector(const small_vector &other) 498 : base_type( initial_capacity_t(), internal_capacity() 499 , allocator_traits_type::select_on_container_copy_construction(other.get_stored_allocator())) 500 { this->assign(other.cbegin(), other.cend()); } 501 small_vector(const small_vector & other,const allocator_type & a)502 small_vector(const small_vector &other, const allocator_type &a) 503 : base_type(initial_capacity_t(), internal_capacity(), a) 504 { this->assign(other.cbegin(), other.cend()); } 505 small_vector(BOOST_RV_REF (small_vector)other)506 small_vector(BOOST_RV_REF(small_vector) other) 507 : base_type(initial_capacity_t(), internal_capacity(), ::boost::move(other.get_stored_allocator())) 508 { this->move_construct_impl(other, other.get_stored_allocator()); } 509 small_vector(BOOST_RV_REF (small_vector)other,const allocator_type & a)510 small_vector(BOOST_RV_REF(small_vector) other, const allocator_type &a) 511 : base_type(initial_capacity_t(), internal_capacity(), a) 512 { this->move_construct_impl(other, a); } 513 514 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) small_vector(std::initializer_list<value_type> il,const allocator_type & a=allocator_type ())515 small_vector(std::initializer_list<value_type> il, const allocator_type& a = allocator_type()) 516 : base_type(initial_capacity_t(), internal_capacity(), a) 517 { 518 this->assign(il.begin(), il.end()); 519 } 520 #endif 521 operator =(BOOST_COPY_ASSIGN_REF (small_vector)other)522 small_vector& operator=(BOOST_COPY_ASSIGN_REF(small_vector) other) 523 { return static_cast<small_vector&>(this->base_type::operator=(static_cast<base_type const&>(other))); } 524 operator =(BOOST_RV_REF (small_vector)other)525 small_vector& operator=(BOOST_RV_REF(small_vector) other) 526 { return static_cast<small_vector&>(this->base_type::operator=(BOOST_MOVE_BASE(base_type, other))); } 527 swap(small_vector & other)528 void swap(small_vector &other) 529 { return this->base_type::swap(other); } 530 531 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 532 private: move_construct_impl(small_vector & x,const allocator_type & a)533 void move_construct_impl(small_vector &x, const allocator_type &a) 534 { 535 if(base_type::is_propagable_from(x.get_stored_allocator(), x.data(), a, true)){ 536 this->steal_resources(x); 537 } 538 else{ 539 this->assign( boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.begin())) 540 , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.end ())) 541 ); 542 } 543 } 544 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 545 }; 546 547 }} 548 549 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 550 /* 551 namespace boost { 552 553 //!has_trivial_destructor_after_move<> == true_type 554 //!specialization for optimizations 555 template <class T, class Allocator> 556 struct has_trivial_destructor_after_move<boost::container::vector<T, Allocator> > 557 { 558 typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; 559 static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && 560 ::boost::has_trivial_destructor_after_move<pointer>::value; 561 }; 562 563 } 564 */ 565 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 566 567 #include <boost/container/detail/config_end.hpp> 568 569 #endif // #ifndef BOOST_CONTAINER_CONTAINER_SMALL_VECTOR_HPP 570