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)92 BOOST_COPYABLE_AND_MOVABLE(small_vector_allocator) 93 94 BOOST_CONTAINER_FORCEINLINE const Allocator &as_base() const 95 { return static_cast<const Allocator&>(*this); } 96 as_base()97 BOOST_CONTAINER_FORCEINLINE 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 BOOST_CONTAINER_FORCEINLINE 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 BOOST_CONTAINER_FORCEINLINE explicit small_vector_allocator(BOOST_MOVE_UREF##N)\ 145 : Allocator(BOOST_MOVE_FWD##N)\ 146 {}\ 147 // BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SMALL_VECTOR_ALLOCATOR_CTOR_CODE)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 154 BOOST_CONTAINER_FORCEINLINE small_vector_allocator 155 (const small_vector_allocator &other) BOOST_NOEXCEPT_OR_NOTHROW 156 : Allocator(other.as_base()) 157 {} 158 159 //!Move constructor from small_vector_allocator. 160 //!Never throws small_vector_allocator(BOOST_RV_REF (small_vector_allocator)other)161 BOOST_CONTAINER_FORCEINLINE small_vector_allocator 162 (BOOST_RV_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW 163 : Allocator(::boost::move(other.as_base())) 164 {} 165 166 //!Constructor from related small_vector_allocator. 167 //!Never throws 168 template<class OtherAllocator> small_vector_allocator(const small_vector_allocator<OtherAllocator> & other)169 BOOST_CONTAINER_FORCEINLINE small_vector_allocator 170 (const small_vector_allocator<OtherAllocator> &other) BOOST_NOEXCEPT_OR_NOTHROW 171 : Allocator(other.as_base()) 172 {} 173 174 //!Move constructor from related small_vector_allocator. 175 //!Never throws 176 template<class OtherAllocator> small_vector_allocator(BOOST_RV_REF (small_vector_allocator<OtherAllocator>)other)177 BOOST_CONTAINER_FORCEINLINE small_vector_allocator 178 (BOOST_RV_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW 179 : Allocator(::boost::move(other.as_base())) 180 {} 181 182 //!Assignment from other small_vector_allocator. 183 //!Never throws 184 BOOST_CONTAINER_FORCEINLINE small_vector_allocator & operator =(BOOST_COPY_ASSIGN_REF (small_vector_allocator)other)185 operator=(BOOST_COPY_ASSIGN_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW 186 { return static_cast<small_vector_allocator&>(this->Allocator::operator=(other.as_base())); } 187 188 //!Move constructor from other small_vector_allocator. 189 //!Never throws 190 BOOST_CONTAINER_FORCEINLINE small_vector_allocator & operator =(BOOST_RV_REF (small_vector_allocator)other)191 operator=(BOOST_RV_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW 192 { return static_cast<small_vector_allocator&>(this->Allocator::operator=(::boost::move(other.as_base()))); } 193 194 //!Assignment from related small_vector_allocator. 195 //!Never throws 196 template<class OtherAllocator> 197 BOOST_CONTAINER_FORCEINLINE small_vector_allocator & operator =(BOOST_COPY_ASSIGN_REF (small_vector_allocator<OtherAllocator>)other)198 operator=(BOOST_COPY_ASSIGN_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW 199 { return static_cast<small_vector_allocator&>(this->Allocator::operator=(other.as_base())); } 200 201 //!Move assignment from related small_vector_allocator. 202 //!Never throws 203 template<class OtherAllocator> 204 BOOST_CONTAINER_FORCEINLINE small_vector_allocator & operator =(BOOST_RV_REF (small_vector_allocator<OtherAllocator>)other)205 operator=(BOOST_RV_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW 206 { return static_cast<small_vector_allocator&>(this->Allocator::operator=(::boost::move(other.as_base()))); } 207 208 //!Allocates storage from the standard-conforming allocator allocate(size_type count,const_void_pointer hint=const_void_pointer ())209 BOOST_CONTAINER_FORCEINLINE pointer allocate(size_type count, const_void_pointer hint = const_void_pointer()) 210 { return allocator_traits_type::allocate(this->as_base(), count, hint); } 211 212 //!Deallocates previously allocated memory. 213 //!Never throws deallocate(pointer ptr,size_type n)214 void deallocate(pointer ptr, size_type n) BOOST_NOEXCEPT_OR_NOTHROW 215 { 216 if(!this->is_internal_storage(ptr)) 217 allocator_traits_type::deallocate(this->as_base(), ptr, n); 218 } 219 220 //!Returns the maximum number of elements that could be allocated. 221 //!Never throws max_size() const222 BOOST_CONTAINER_FORCEINLINE size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW 223 { return allocator_traits_type::max_size(this->as_base()); } 224 select_on_container_copy_construction() const225 small_vector_allocator select_on_container_copy_construction() const 226 { return small_vector_allocator(allocator_traits_type::select_on_container_copy_construction(this->as_base())); } 227 storage_is_unpropagable(pointer p) const228 bool storage_is_unpropagable(pointer p) const 229 { return this->is_internal_storage(p) || allocator_traits_type::storage_is_unpropagable(this->as_base(), p); } 230 231 //!Swaps two allocators, does nothing 232 //!because this small_vector_allocator is stateless swap(small_vector_allocator & l,small_vector_allocator & r)233 BOOST_CONTAINER_FORCEINLINE friend void swap(small_vector_allocator &l, small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW 234 { boost::adl_move_swap(l.as_base(), r.as_base()); } 235 236 //!An small_vector_allocator always compares to true, as memory allocated with one 237 //!instance can be deallocated by another instance (except for unpropagable storage) operator ==(const small_vector_allocator & l,const small_vector_allocator & r)238 BOOST_CONTAINER_FORCEINLINE friend bool operator==(const small_vector_allocator &l, const small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW 239 { return allocator_traits_type::equal(l.as_base(), r.as_base()); } 240 241 //!An small_vector_allocator always compares to false, as memory allocated with one 242 //!instance can be deallocated by another instance operator !=(const small_vector_allocator & l,const small_vector_allocator & r)243 BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const small_vector_allocator &l, const small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW 244 { return !(l == r); } 245 246 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 247 /* 248 //!An advanced function that offers in-place expansion shrink to fit and new allocation 249 //!capabilities. Memory allocated with this function can only be deallocated with deallocate() 250 //!or deallocate_many(). 251 //!This function is available only with Version == 2 252 pointer allocation_command(allocation_type command, 253 size_type limit_size, 254 size_type &prefer_in_recvd_out_size, 255 pointer &reuse) 256 { return allocator_traits_type::allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); } 257 258 //!Returns maximum the number of objects the previously allocated memory 259 //!pointed by p can hold. 260 //!Memory must not have been allocated with 261 //!allocate_one or allocate_individual. 262 //!This function is available only with Version == 2 263 size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW 264 { return allocator_traits_type::size(p); } 265 */ 266 private: 267 /* 268 //!Allocates just one object. Memory allocated with this function 269 //!must be deallocated only with deallocate_one(). 270 //!Throws bad_alloc if there is no enough memory 271 //!This function is available only with Version == 2 272 using Allocator::allocate_one; 273 using Allocator::allocate_individual; 274 using Allocator::deallocate_one; 275 using Allocator::deallocate_individual; 276 using Allocator::allocate_many; 277 using Allocator::deallocate_many;*/ 278 is_internal_storage(pointer p) const279 BOOST_CONTAINER_FORCEINLINE bool is_internal_storage(pointer p) const 280 { return this->internal_storage() == p; } 281 internal_storage() const282 pointer internal_storage() const 283 { 284 typedef typename Allocator::value_type value_type; 285 typedef container_detail::vector_alloc_holder< small_vector_allocator<Allocator> > vector_alloc_holder_t; 286 typedef vector<value_type, small_vector_allocator<Allocator> > vector_base; 287 typedef small_vector_base<value_type, Allocator> derived_type; 288 // 289 const vector_alloc_holder_t &v_holder = static_cast<const vector_alloc_holder_t &>(*this); 290 const vector_base &v_base = reinterpret_cast<const vector_base &>(v_holder); 291 const derived_type &d_base = static_cast<const derived_type &>(v_base); 292 return d_base.internal_storage(); 293 } 294 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 295 }; 296 297 //! This class consists of common code from all small_vector<T, N> types that don't depend on the 298 //! "N" template parameter. This class is non-copyable and non-destructible, so this class typically 299 //! used as reference argument to functions that read or write small vectors. Since `small_vector<T, N>` 300 //! derives from `small_vector_base<T>`, the conversion to `small_vector_base` is implicit 301 //! <pre> 302 //! 303 //! //Clients can pass any small_vector<Foo, N>. 304 //! void read_any_small_vector_of_foo(const small_vector_base<Foo> &in_parameter); 305 //! 306 //! void modify_any_small_vector_of_foo(small_vector_base<Foo> &in_out_parameter); 307 //! 308 //! void some_function() 309 //! { 310 //! 311 //! small_vector<Foo, 8> myvector; 312 //! 313 //! read_any_small_vector_of_foo(myvector); // Reads myvector 314 //! 315 //! modify_any_small_vector_of_foo(myvector); // Modifies myvector 316 //! 317 //! } 318 //! </pre> 319 //! 320 //! All `boost::container:vector` member functions are inherited. See `vector` documentation for details. 321 //! 322 template <class T, class SecondaryAllocator> 323 class small_vector_base 324 : public vector<T, small_vector_allocator<SecondaryAllocator> > 325 { 326 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 327 public: 328 //Make it public as it will be inherited by small_vector and container 329 //must have this public member 330 typedef typename allocator_traits<SecondaryAllocator>::pointer pointer; 331 332 private: 333 BOOST_COPYABLE_AND_MOVABLE(small_vector_base) 334 335 friend class small_vector_allocator<SecondaryAllocator>; 336 internal_storage() const337 pointer internal_storage() const BOOST_NOEXCEPT_OR_NOTHROW 338 { 339 return boost::intrusive::pointer_traits<pointer>::pointer_to 340 (*const_cast<T*>(static_cast<const T*>(static_cast<const void*>(&m_storage_start)))); 341 } 342 343 typedef vector<T, small_vector_allocator<SecondaryAllocator> > base_type; as_base()344 base_type &as_base() { return static_cast<base_type&>(*this); } as_base() const345 const base_type &as_base() const { return static_cast<const base_type&>(*this); } 346 347 public: 348 typedef typename container_detail::aligned_storage 349 <sizeof(T), container_detail::alignment_of<T>::value>::type storage_type; 350 typedef small_vector_allocator<SecondaryAllocator> allocator_type; 351 352 protected: 353 typedef typename base_type::initial_capacity_t initial_capacity_t; 354 small_vector_base(initial_capacity_t,std::size_t initial_capacity)355 BOOST_CONTAINER_FORCEINLINE explicit small_vector_base(initial_capacity_t, std::size_t initial_capacity) 356 : base_type(initial_capacity_t(), this->internal_storage(), initial_capacity) 357 {} 358 359 template<class AllocFwd> small_vector_base(initial_capacity_t,std::size_t capacity,BOOST_FWD_REF (AllocFwd)a)360 BOOST_CONTAINER_FORCEINLINE explicit small_vector_base(initial_capacity_t, std::size_t capacity, BOOST_FWD_REF(AllocFwd) a) 361 : base_type(initial_capacity_t(), this->internal_storage(), capacity, ::boost::forward<AllocFwd>(a)) 362 {} 363 364 //~small_vector_base(){} 365 366 private: 367 //The only member 368 storage_type m_storage_start; 369 370 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 371 372 public: operator =(BOOST_COPY_ASSIGN_REF (small_vector_base)other)373 BOOST_CONTAINER_FORCEINLINE small_vector_base& operator=(BOOST_COPY_ASSIGN_REF(small_vector_base) other) 374 { return static_cast<small_vector_base&>(this->base_type::operator=(static_cast<base_type const&>(other))); } 375 operator =(BOOST_RV_REF (small_vector_base)other)376 BOOST_CONTAINER_FORCEINLINE small_vector_base& operator=(BOOST_RV_REF(small_vector_base) other) 377 { return static_cast<small_vector_base&>(this->base_type::operator=(BOOST_MOVE_BASE(base_type, other))); } 378 swap(small_vector_base & other)379 BOOST_CONTAINER_FORCEINLINE void swap(small_vector_base &other) 380 { return this->base_type::swap(other); } 381 382 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 383 protected: move_construct_impl(base_type & x,const allocator_type & a)384 void move_construct_impl(base_type &x, const allocator_type &a) 385 { 386 if(base_type::is_propagable_from(x.get_stored_allocator(), x.data(), a, true)){ 387 this->steal_resources(x); 388 } 389 else{ 390 this->assign( boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.begin())) 391 , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.end ())) 392 ); 393 } 394 } 395 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 396 }; 397 398 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 399 400 ///////////////////////////////////////////////////// 401 // 402 // small_vector_storage_calculator 403 // 404 ///////////////////////////////////////////////////// 405 template<std::size_t Needed, std::size_t Hdr, std::size_t SSize, bool NeedsZero = (0u == Needed || Needed <= Hdr)> 406 struct small_vector_storage_calculator_helper 407 { 408 static const std::size_t value = (Needed - Hdr - 1u)/SSize + 1u; 409 }; 410 411 template<std::size_t Needed, std::size_t Hdr, std::size_t SSize> 412 struct small_vector_storage_calculator_helper<Needed, Hdr, SSize, true> 413 { 414 static const std::size_t value = 0u; 415 }; 416 417 template<class Storage, class Allocator, class T, std::size_t N> 418 struct small_vector_storage_calculator 419 { 420 typedef small_vector_base<T, Allocator> svh_type; 421 typedef vector<T, small_vector_allocator<Allocator> > svhb_type; 422 static const std::size_t s_align = container_detail::alignment_of<Storage>::value; 423 static const std::size_t s_size = sizeof(Storage); 424 static const std::size_t svh_sizeof = sizeof(svh_type); 425 static const std::size_t svhb_sizeof = sizeof(svhb_type); 426 static const std::size_t s_start = ((svhb_sizeof-1)/s_align+1)*s_align; 427 static const std::size_t header_bytes = svh_sizeof-s_start; 428 static const std::size_t needed_bytes = sizeof(T)*N; 429 static const std::size_t needed_extra_storages = 430 small_vector_storage_calculator_helper<needed_bytes, header_bytes, s_size>::value; 431 }; 432 433 ///////////////////////////////////////////////////// 434 // 435 // small_vector_storage_definer 436 // 437 ///////////////////////////////////////////////////// 438 template<class Storage, std::size_t N> 439 struct small_vector_storage 440 { 441 Storage m_rest_of_storage[N]; 442 }; 443 444 template<class Storage> 445 struct small_vector_storage<Storage, 0> 446 {}; 447 448 template<class Allocator, std::size_t N> 449 struct small_vector_storage_definer 450 { 451 typedef typename Allocator::value_type value_type; 452 typedef typename small_vector_base<value_type, Allocator>::storage_type storage_type; 453 static const std::size_t needed_extra_storages = 454 small_vector_storage_calculator<storage_type, Allocator, value_type, N>::needed_extra_storages; 455 typedef small_vector_storage<storage_type, needed_extra_storages> type; 456 }; 457 458 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 459 460 //! small_vector is a vector-like container optimized for the case when it contains few elements. 461 //! It contains some preallocated elements in-place, which can avoid the use of dynamic storage allocation 462 //! when the actual number of elements is below that preallocated threshold. 463 //! 464 //! `small_vector<T, N, Allocator>` is convertible to `small_vector_base<T, Allocator>` that is independent 465 //! from the preallocated element capacity, so client code does not need to be templated on that N argument. 466 //! 467 //! All `boost::container::vector` member functions are inherited. See `vector` documentation for details. 468 //! 469 //! \tparam T The type of object that is stored in the small_vector 470 //! \tparam N The number of preallocated elements stored inside small_vector. It shall be less than Allocator::max_size(); 471 //! \tparam Allocator The allocator used for memory management when the number of elements exceeds N. 472 template <class T, std::size_t N, class Allocator BOOST_CONTAINER_DOCONLY(= new_allocator<T>) > 473 class small_vector : public small_vector_base<T, Allocator> 474 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 475 , private small_vector_storage_definer<Allocator, N>::type 476 #endif 477 { 478 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 479 typedef small_vector_base<T, Allocator> base_type; 480 typedef typename small_vector_storage_definer<Allocator, N>::type remaining_storage_holder; 481 482 BOOST_COPYABLE_AND_MOVABLE(small_vector) 483 484 typedef typename base_type::initial_capacity_t initial_capacity_t; 485 typedef allocator_traits<typename base_type::allocator_type> allocator_traits_type; 486 487 public: 488 typedef small_vector_storage_calculator< typename small_vector_base<T, Allocator> 489 ::storage_type, Allocator, T, N> storage_test; 490 491 static const std::size_t needed_extra_storages = storage_test::needed_extra_storages; 492 static const std::size_t needed_bytes = storage_test::needed_bytes; 493 static const std::size_t header_bytes = storage_test::header_bytes; 494 static const std::size_t s_start = storage_test::s_start; 495 496 typedef typename base_type::allocator_type allocator_type; 497 typedef typename base_type::size_type size_type; 498 typedef typename base_type::value_type value_type; 499 internal_capacity()500 BOOST_CONTAINER_FORCEINLINE static std::size_t internal_capacity() 501 { return (sizeof(small_vector) - storage_test::s_start)/sizeof(T); } 502 503 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 504 505 //! @brief The capacity/max size of the container 506 static const size_type static_capacity = N; 507 508 public: small_vector()509 BOOST_CONTAINER_FORCEINLINE small_vector() 510 BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value) 511 : base_type(initial_capacity_t(), internal_capacity()) 512 {} 513 small_vector(const allocator_type & a)514 BOOST_CONTAINER_FORCEINLINE explicit small_vector(const allocator_type &a) 515 : base_type(initial_capacity_t(), internal_capacity(), a) 516 {} 517 small_vector(size_type n)518 BOOST_CONTAINER_FORCEINLINE explicit small_vector(size_type n) 519 : base_type(initial_capacity_t(), internal_capacity()) 520 { this->resize(n); } 521 small_vector(size_type n,const allocator_type & a)522 BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, const allocator_type &a) 523 : base_type(initial_capacity_t(), internal_capacity(), a) 524 { this->resize(n); } 525 small_vector(size_type n,default_init_t)526 BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, default_init_t) 527 : base_type(initial_capacity_t(), internal_capacity()) 528 { this->resize(n, default_init_t()); } 529 small_vector(size_type n,default_init_t,const allocator_type & a)530 BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, default_init_t, const allocator_type &a) 531 : base_type(initial_capacity_t(), internal_capacity(), a) 532 { this->resize(n, default_init_t()); } 533 small_vector(size_type n,const value_type & v)534 BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, const value_type &v) 535 : base_type(initial_capacity_t(), internal_capacity()) 536 { this->resize(n, v); } 537 small_vector(size_type n,const value_type & v,const allocator_type & a)538 BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, const value_type &v, const allocator_type &a) 539 : base_type(initial_capacity_t(), internal_capacity(), a) 540 { this->resize(n, v); } 541 542 template <class InIt> 543 BOOST_CONTAINER_FORCEINLINE small_vector(InIt first, InIt last 544 BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::disable_if_c 545 < container_detail::is_convertible<InIt BOOST_MOVE_I size_type>::value 546 BOOST_MOVE_I container_detail::nat >::type * = 0) 547 ) 548 : base_type(initial_capacity_t(), internal_capacity()) 549 { this->assign(first, last); } 550 551 template <class InIt> 552 BOOST_CONTAINER_FORCEINLINE small_vector(InIt first, InIt last, const allocator_type& a 553 BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::disable_if_c 554 < container_detail::is_convertible<InIt BOOST_MOVE_I size_type>::value 555 BOOST_MOVE_I container_detail::nat >::type * = 0) 556 ) 557 : base_type(initial_capacity_t(), internal_capacity(), a) 558 { this->assign(first, last); } 559 small_vector(const small_vector & other)560 BOOST_CONTAINER_FORCEINLINE small_vector(const small_vector &other) 561 : base_type( initial_capacity_t(), internal_capacity() 562 , allocator_traits_type::select_on_container_copy_construction(other.get_stored_allocator())) 563 { this->assign(other.cbegin(), other.cend()); } 564 small_vector(const small_vector & other,const allocator_type & a)565 BOOST_CONTAINER_FORCEINLINE small_vector(const small_vector &other, const allocator_type &a) 566 : base_type(initial_capacity_t(), internal_capacity(), a) 567 { this->assign(other.cbegin(), other.cend()); } 568 small_vector(const base_type & other)569 BOOST_CONTAINER_FORCEINLINE explicit small_vector(const base_type &other) 570 : base_type( initial_capacity_t(), internal_capacity() 571 , allocator_traits_type::select_on_container_copy_construction(other.get_stored_allocator())) 572 { this->assign(other.cbegin(), other.cend()); } 573 small_vector(BOOST_RV_REF (base_type)other)574 BOOST_CONTAINER_FORCEINLINE explicit small_vector(BOOST_RV_REF(base_type) other) 575 : base_type(initial_capacity_t(), internal_capacity(), ::boost::move(other.get_stored_allocator())) 576 { this->move_construct_impl(other, other.get_stored_allocator()); } 577 small_vector(BOOST_RV_REF (small_vector)other)578 BOOST_CONTAINER_FORCEINLINE small_vector(BOOST_RV_REF(small_vector) other) 579 : base_type(initial_capacity_t(), internal_capacity(), ::boost::move(other.get_stored_allocator())) 580 { this->move_construct_impl(other, other.get_stored_allocator()); } 581 small_vector(BOOST_RV_REF (small_vector)other,const allocator_type & a)582 BOOST_CONTAINER_FORCEINLINE small_vector(BOOST_RV_REF(small_vector) other, const allocator_type &a) 583 : base_type(initial_capacity_t(), internal_capacity(), a) 584 { this->move_construct_impl(other, a); } 585 586 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) small_vector(std::initializer_list<value_type> il,const allocator_type & a=allocator_type ())587 BOOST_CONTAINER_FORCEINLINE small_vector(std::initializer_list<value_type> il, const allocator_type& a = allocator_type()) 588 : base_type(initial_capacity_t(), internal_capacity(), a) 589 { 590 this->assign(il.begin(), il.end()); 591 } 592 #endif 593 operator =(BOOST_COPY_ASSIGN_REF (small_vector)other)594 BOOST_CONTAINER_FORCEINLINE small_vector& operator=(BOOST_COPY_ASSIGN_REF(small_vector) other) 595 { return static_cast<small_vector&>(this->base_type::operator=(static_cast<base_type const&>(other))); } 596 operator =(BOOST_RV_REF (small_vector)other)597 BOOST_CONTAINER_FORCEINLINE small_vector& operator=(BOOST_RV_REF(small_vector) other) 598 { return static_cast<small_vector&>(this->base_type::operator=(BOOST_MOVE_BASE(base_type, other))); } 599 operator =(const base_type & other)600 BOOST_CONTAINER_FORCEINLINE small_vector& operator=(const base_type &other) 601 { return static_cast<small_vector&>(this->base_type::operator=(other)); } 602 operator =(BOOST_RV_REF (base_type)other)603 BOOST_CONTAINER_FORCEINLINE small_vector& operator=(BOOST_RV_REF(base_type) other) 604 { return static_cast<small_vector&>(this->base_type::operator=(boost::move(other))); } 605 swap(small_vector & other)606 BOOST_CONTAINER_FORCEINLINE void swap(small_vector &other) 607 { return this->base_type::swap(other); } 608 }; 609 610 }} 611 612 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 613 /* 614 namespace boost { 615 616 //!has_trivial_destructor_after_move<> == true_type 617 //!specialization for optimizations 618 template <class T, class Allocator> 619 struct has_trivial_destructor_after_move<boost::container::vector<T, Allocator> > 620 { 621 typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; 622 static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && 623 ::boost::has_trivial_destructor_after_move<pointer>::value; 624 }; 625 626 } 627 */ 628 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED 629 630 #include <boost/container/detail/config_end.hpp> 631 632 #endif // #ifndef BOOST_CONTAINER_CONTAINER_SMALL_VECTOR_HPP 633