1 // Boost.Container varray
2 //
3 // Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland.
4 // Copyright (c) 2011-2013 Andrew Hundt.
5 // Copyright (c) 2014-2014 Ion Gaztanaga
6 //
7 // Use, modification and distribution is subject to the Boost Software License,
8 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 
11 #ifndef BOOST_CONTAINER_DETAIL_VARRAY_HPP
12 #define BOOST_CONTAINER_DETAIL_VARRAY_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 #include <boost/container/detail/addressof.hpp>
26 #include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare
27 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
28 #include <boost/move/detail/fwd_macros.hpp>
29 #endif
30 #include <boost/container/detail/iterator.hpp>
31 #include <boost/container/detail/iterators.hpp>
32 #include <boost/container/detail/mpl.hpp>
33 #include <boost/container/detail/type_traits.hpp>
34 #include <boost/move/adl_move_swap.hpp> //adl_move_swap
35 
36 
37 #include "varray_util.hpp"
38 
39 #include <boost/assert.hpp>
40 #include <boost/config.hpp>
41 
42 #include <boost/static_assert.hpp>
43 
44 #ifndef BOOST_NO_EXCEPTIONS
45 #include <stdexcept>
46 #endif // BOOST_NO_EXCEPTIONS
47 
48 
49 /**
50  * @defgroup varray_non_member varray non-member functions
51  */
52 
53 namespace boost { namespace container { namespace dtl {
54 
55 // Forward declaration
56 template <typename Value, std::size_t Capacity, typename Strategy>
57 class varray;
58 
59 namespace strategy {
60 
61 // TODO: Improve error messages
62 //       possibly include N in the strategy, and provide size as an optoinal allocate_failed parameter?
63 //       Example of current error with reserve(4) when capacity is 3:
64 //          "boost/container/varray.hpp(66): size can't exceed the capacity"
65 //       Could say
66 //          "cannot reserve(4) due to fixed capacity of 3 elements"
67 
68 //! @brief The default strategy.
69 //!
70 //! @tparam Value Type of element stored in the container.
71 template <typename Value>
72 struct def
73 {
74     typedef Value value_type;
75     typedef std::size_t size_type;
76     typedef std::ptrdiff_t difference_type;
77     typedef Value* pointer;
78     typedef const Value* const_pointer;
79     typedef Value& reference;
80     typedef const Value& const_reference;
81 
allocate_failedboost::container::dtl::strategy::def82     static void allocate_failed()
83     {
84         BOOST_ASSERT_MSG(false, "size can't exceed the capacity");
85     }
86 };
87 
88 //! @brief The strategy adapting info from passed Allocator.
89 //!
90 //! This strategy defines the same types that are defined in the Allocator.
91 //!
92 //! @tparam Allocator The Allocator which will be adapted.
93 template <typename Allocator>
94 struct allocator_adaptor
95 {
96     typedef typename Allocator::value_type value_type;
97     typedef typename Allocator::size_type size_type;
98     typedef typename Allocator::difference_type difference_type;
99     typedef typename Allocator::pointer pointer;
100     typedef typename Allocator::const_pointer const_pointer;
101     typedef typename Allocator::reference reference;
102     typedef typename Allocator::const_reference const_reference;
103 
allocate_failedboost::container::dtl::strategy::allocator_adaptor104     static void allocate_failed()
105     {
106         BOOST_ASSERT_MSG(false, "size can't exceed the capacity");
107     }
108 };
109 
110 } // namespace strategy
111 
112 struct varray_error_handler
113 {
114     template <typename V, std::size_t Capacity, typename S>
check_capacityboost::container::dtl::varray_error_handler115     static void check_capacity(varray<V, Capacity, S> const&, std::size_t s)
116     {
117         if ( Capacity < s )
118             S::allocate_failed();
119     }
120 
121     template <typename V, std::size_t C, typename S>
check_atboost::container::dtl::varray_error_handler122     static void check_at(varray<V, C, S> const& v,
123                          typename varray<V, C, S>::size_type i)
124     {
125         (void)v;
126         (void)i;
127 // TODO - use BOOST_THROW_EXCEPTION here?
128 #ifndef BOOST_NO_EXCEPTIONS
129         if ( v.size() <= i )
130             throw std::out_of_range("index out of bounds");
131 #else // BOOST_NO_EXCEPTIONS
132         BOOST_ASSERT_MSG(i < v.size(), "index out of bounds");
133 #endif // BOOST_NO_EXCEPTIONS
134     }
135 
136     template <typename V, std::size_t C, typename S>
check_operator_bracketsboost::container::dtl::varray_error_handler137     static void check_operator_brackets(varray<V, C, S> const& v,
138                                         typename varray<V, C, S>::size_type i)
139     {
140         (void)v;
141         (void)i;
142         BOOST_ASSERT_MSG(i < v.size(), "index out of bounds");
143     }
144 
145     template <typename V, std::size_t C, typename S>
check_emptyboost::container::dtl::varray_error_handler146     static void check_empty(varray<V, C, S> const& v)
147     {
148         (void)v;
149         BOOST_ASSERT_MSG(0 < v.size(), "the container is empty");
150     }
151 
152     template <typename V, std::size_t C, typename S>
check_iterator_end_neqboost::container::dtl::varray_error_handler153     static void check_iterator_end_neq(varray<V, C, S> const& v,
154                                        typename varray<V, C, S>::const_iterator position)
155     {
156         (void)v;
157         (void)position;
158         BOOST_ASSERT_MSG(v.begin() <= position && position < v.end(), "iterator out of bounds");
159     }
160 
161     template <typename V, std::size_t C, typename S>
check_iterator_end_eqboost::container::dtl::varray_error_handler162     static void check_iterator_end_eq(varray<V, C, S> const& v,
163                                       typename varray<V, C, S>::const_iterator position)
164     {
165         (void)v;
166         (void)position;
167         BOOST_ASSERT_MSG(v.begin() <= position && position <= v.end(), "iterator out of bounds");
168     }
169 };
170 
171 template <typename Value, std::size_t Capacity, typename Strategy>
172 struct varray_traits
173 {
174     typedef typename Strategy::value_type value_type;
175     typedef typename Strategy::size_type size_type;
176     typedef typename Strategy::difference_type difference_type;
177     typedef typename Strategy::pointer pointer;
178     typedef typename Strategy::const_pointer const_pointer;
179     typedef typename Strategy::reference reference;
180     typedef typename Strategy::const_reference const_reference;
181 
182     typedef varray_error_handler error_handler;
183 
184     typedef false_type use_memop_in_swap_and_move;
185     typedef false_type use_optimized_swap;
186     typedef false_type disable_trivial_init;
187 };
188 
189 /**
190  * @brief A variable-size array container with fixed capacity.
191  *
192  * varray is a sequence container like boost::container::vector with contiguous storage that can
193  * change in size, along with the static allocation, low overhead, and fixed capacity of boost::array.
194  *
195  * A varray is a sequence that supports random access to elements, constant time insertion and
196  * removal of elements at the end, and linear time insertion and removal of elements at the beginning or
197  * in the middle. The number of elements in a varray may vary dynamically up to a fixed capacity
198  * because elements are stored within the object itself similarly to an array. However, objects are
199  * initialized as they are inserted into varray unlike C arrays or std::array which must construct
200  * all elements on instantiation. The behavior of varray enables the use of statically allocated
201  * elements in cases with complex object lifetime requirements that would otherwise not be trivially
202  * possible.
203  *
204  * @par Error Handling
205  *  Insertion beyond the capacity and out of bounds errors result in undefined behavior unless
206  *  otherwise specified. In this respect if size() == capacity(), then varray::push_back()
207  *  behaves like std::vector pop_front() if size() == empty(). The reason for this difference
208  *  is because unlike vectors, varray does not perform allocation.
209  *
210  * @par Advanced Usage
211  *  Error handling behavior can be modified to more closely match std::vector exception behavior
212  *  when exceeding bounds by providing an alternate Strategy and varray_traits instantiation.
213  *
214  * @tparam Value    The type of element that will be stored.
215  * @tparam Capacity The maximum number of elements varray can store, fixed at compile time.
216  * @tparam Strategy Defines the public typedefs and error handlers,
217  *         implements StaticVectorStrategy and has some similarities
218  *         to an Allocator.
219  */
220 template <typename Value, std::size_t Capacity, typename Strategy = strategy::def<Value> >
221 class varray
222 {
223     typedef dtl::varray_traits<
224         Value, Capacity, Strategy
225     > vt;
226 
227     typedef typename vt::error_handler errh;
228     typedef typename aligned_storage<
229         sizeof(Value[Capacity]),
230         boost::container::dtl::alignment_of<Value[Capacity]>::value
231     >::type aligned_storage_type;
232 
233     template <typename V, std::size_t C, typename S>
234     friend class varray;
235 
236     BOOST_COPYABLE_AND_MOVABLE(varray)
237 
238 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
239 public:
240     template <std::size_t C, typename S>
operator =(varray<Value,C,S> & sv)241     varray & operator=(varray<Value, C, S> & sv)
242     {
243         typedef varray<Value, C, S> other;
244         this->operator=(static_cast<const ::boost::rv<other> &>(const_cast<const other &>(sv)));
245         return *this;
246     }
247 #endif
248 
249 public:
250     //! @brief The type of elements stored in the container.
251     typedef typename vt::value_type value_type;
252     //! @brief The unsigned integral type used by the container.
253     typedef typename vt::size_type size_type;
254     //! @brief The pointers difference type.
255     typedef typename vt::difference_type difference_type;
256     //! @brief The pointer type.
257     typedef typename vt::pointer pointer;
258     //! @brief The const pointer type.
259     typedef typename vt::const_pointer const_pointer;
260     //! @brief The value reference type.
261     typedef typename vt::reference reference;
262     //! @brief The value const reference type.
263     typedef typename vt::const_reference const_reference;
264 
265     //! @brief The iterator type.
266     typedef pointer iterator;
267     //! @brief The const iterator type.
268     typedef const_pointer const_iterator;
269     //! @brief The reverse iterator type.
270     typedef boost::container::reverse_iterator<iterator> reverse_iterator;
271     //! @brief The const reverse iterator.
272     typedef boost::container::reverse_iterator<const_iterator> const_reverse_iterator;
273 
274     //! @brief The type of a strategy used by the varray.
275     typedef Strategy strategy_type;
276 
277     //! @brief Constructs an empty varray.
278     //!
279     //! @par Throws
280     //!   Nothing.
281     //!
282     //! @par Complexity
283     //!   Constant O(1).
varray()284     varray()
285         : m_size(0)
286     {}
287 
288     //! @pre <tt>count <= capacity()</tt>
289     //!
290     //! @brief Constructs a varray containing count value initialized Values.
291     //!
292     //! @param count    The number of values which will be contained in the container.
293     //!
294     //! @par Throws
295     //!   If Value's value initialization throws.
296     //! @internal
297     //!   @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
298     //! @endinternal
299     //!
300     //! @par Complexity
301     //!   Linear O(N).
varray(size_type count)302     explicit varray(size_type count)
303         : m_size(0)
304     {
305         this->resize(count);                                                        // may throw
306     }
307 
308     //! @pre <tt>count <= capacity()</tt>
309     //!
310     //! @brief Constructs a varray containing count copies of value.
311     //!
312     //! @param count    The number of copies of a values that will be contained in the container.
313     //! @param value    The value which will be used to copy construct values.
314     //!
315     //! @par Throws
316     //!   If Value's copy constructor throws.
317     //! @internal
318     //!   @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
319     //! @endinternal
320     //!
321     //! @par Complexity
322     //!   Linear O(N).
varray(size_type count,value_type const & value)323     varray(size_type count, value_type const& value)
324         : m_size(0)
325     {
326         this->resize(count, value);                                                 // may throw
327     }
328 
329     //! @pre
330     //!  @li <tt>distance(first, last) <= capacity()</tt>
331     //!  @li Iterator must meet the \c ForwardIterator.
332     //!
333     //! @brief Constructs a varray containing copy of a range <tt>[first, last)</tt>.
334     //!
335     //! @param first    The iterator to the first element in range.
336     //! @param last     The iterator to the one after the last element in range.
337     //!
338     //! @par Throws
339     //!   If Value's constructor taking a dereferenced Iterator throws.
340     //! @internal
341     //!   @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
342     //! @endinternal
343     //!
344     //! @par Complexity
345     //!   Linear O(N).
346     template <typename Iterator>
varray(Iterator first,Iterator last)347     varray(Iterator first, Iterator last)
348         : m_size(0)
349     {
350         this->assign(first, last);                                                    // may throw
351     }
352 
353     //! @brief Constructs a copy of other varray.
354     //!
355     //! @param other    The varray which content will be copied to this one.
356     //!
357     //! @par Throws
358     //!   If Value's copy constructor throws.
359     //!
360     //! @par Complexity
361     //!   Linear O(N).
varray(varray const & other)362     varray(varray const& other)
363         : m_size(other.size())
364     {
365         namespace sv = varray_detail;
366         sv::uninitialized_copy(other.begin(), other.end(), this->begin());          // may throw
367     }
368 
369     //! @pre <tt>other.size() <= capacity()</tt>.
370     //!
371     //! @brief Constructs a copy of other varray.
372     //!
373     //! @param other    The varray which content will be copied to this one.
374     //!
375     //! @par Throws
376     //!   If Value's copy constructor throws.
377     //! @internal
378     //!   @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
379     //! @endinternal
380     //!
381     //! @par Complexity
382     //!   Linear O(N).
383     template <std::size_t C, typename S>
varray(varray<value_type,C,S> const & other)384     varray(varray<value_type, C, S> const& other)
385         : m_size(other.size())
386     {
387         errh::check_capacity(*this, other.size());                                  // may throw
388 
389         namespace sv = varray_detail;
390         sv::uninitialized_copy(other.begin(), other.end(), this->begin());          // may throw
391     }
392 
393     //! @brief Copy assigns Values stored in the other varray to this one.
394     //!
395     //! @param other    The varray which content will be copied to this one.
396     //!
397     //! @par Throws
398     //!   If Value's copy constructor or copy assignment throws.
399     //!
400     //! @par Complexity
401     //! Linear O(N).
operator =(BOOST_COPY_ASSIGN_REF (varray)other)402     varray & operator=(BOOST_COPY_ASSIGN_REF(varray) other)
403     {
404         this->assign(other.begin(), other.end());                                     // may throw
405 
406         return *this;
407     }
408 
409     //! @pre <tt>other.size() <= capacity()</tt>
410     //!
411     //! @brief Copy assigns Values stored in the other varray to this one.
412     //!
413     //! @param other    The varray which content will be copied to this one.
414     //!
415     //! @par Throws
416     //!   If Value's copy constructor or copy assignment throws.
417     //! @internal
418     //!   @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
419     //! @endinternal
420     //!
421     //! @par Complexity
422     //!   Linear O(N).
423     template <std::size_t C, typename S>
424 // TEMPORARY WORKAROUND
425 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
operator =(::boost::rv<varray<value_type,C,S>> const & other)426     varray & operator=(::boost::rv< varray<value_type, C, S> > const& other)
427 #else
428     varray & operator=(varray<value_type, C, S> const& other)
429 #endif
430     {
431         this->assign(other.begin(), other.end());                                     // may throw
432 
433         return *this;
434     }
435 
436     //! @brief Move constructor. Moves Values stored in the other varray to this one.
437     //!
438     //! @param other    The varray which content will be moved to this one.
439     //!
440     //! @par Throws
441     //!   @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor throws.
442     //!   @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor throws.
443     //! @internal
444     //!   @li It throws only if \c use_memop_in_swap_and_move is \c false_type - default.
445     //! @endinternal
446     //!
447     //! @par Complexity
448     //!   Linear O(N).
varray(BOOST_RV_REF (varray)other)449     varray(BOOST_RV_REF(varray) other)
450     {
451         typedef typename
452         vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;
453 
454         this->move_ctor_dispatch(other, use_memop_in_swap_and_move());
455     }
456 
457     //! @pre <tt>other.size() <= capacity()</tt>
458     //!
459     //! @brief Move constructor. Moves Values stored in the other varray to this one.
460     //!
461     //! @param other    The varray which content will be moved to this one.
462     //!
463     //! @par Throws
464     //!   @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor throws.
465     //!   @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor throws.
466     //! @internal
467     //!   @li It throws only if \c use_memop_in_swap_and_move is false_type - default.
468     //! @endinternal
469     //! @internal
470     //!   @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
471     //! @endinternal
472     //!
473     //! @par Complexity
474     //!   Linear O(N).
475     template <std::size_t C, typename S>
varray(BOOST_RV_REF_3_TEMPL_ARGS (varray,value_type,C,S)other)476     varray(BOOST_RV_REF_3_TEMPL_ARGS(varray, value_type, C, S) other)
477         : m_size(other.m_size)
478     {
479         errh::check_capacity(*this, other.size());                                  // may throw
480 
481         typedef typename
482         vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;
483 
484         this->move_ctor_dispatch(other, use_memop_in_swap_and_move());
485     }
486 
487     //! @brief Move assignment. Moves Values stored in the other varray to this one.
488     //!
489     //! @param other    The varray which content will be moved to this one.
490     //!
491     //! @par Throws
492     //!   @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws.
493     //!   @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws.
494     //! @internal
495     //!   @li It throws only if \c use_memop_in_swap_and_move is \c false_type - default.
496     //! @endinternal
497     //!
498     //! @par Complexity
499     //!   Linear O(N).
operator =(BOOST_RV_REF (varray)other)500     varray & operator=(BOOST_RV_REF(varray) other)
501     {
502         if ( &other == this )
503             return *this;
504 
505         typedef typename
506         vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;
507 
508         this->move_assign_dispatch(other, use_memop_in_swap_and_move());
509 
510         return *this;
511     }
512 
513     //! @pre <tt>other.size() <= capacity()</tt>
514     //!
515     //! @brief Move assignment. Moves Values stored in the other varray to this one.
516     //!
517     //! @param other    The varray which content will be moved to this one.
518     //!
519     //! @par Throws
520     //!   @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws.
521     //!   @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws.
522     //! @internal
523     //!   @li It throws only if \c use_memop_in_swap_and_move is \c false_type - default.
524     //! @endinternal
525     //! @internal
526     //!   @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
527     //! @endinternal
528     //!
529     //! @par Complexity
530     //!   Linear O(N).
531     template <std::size_t C, typename S>
operator =(BOOST_RV_REF_3_TEMPL_ARGS (varray,value_type,C,S)other)532     varray & operator=(BOOST_RV_REF_3_TEMPL_ARGS(varray, value_type, C, S) other)
533     {
534         errh::check_capacity(*this, other.size());                                  // may throw
535 
536         typedef typename
537         vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;
538 
539         this->move_assign_dispatch(other, use_memop_in_swap_and_move());
540 
541         return *this;
542     }
543 
544     //! @brief Destructor. Destroys Values stored in this container.
545     //!
546     //! @par Throws
547     //!   Nothing
548     //!
549     //! @par Complexity
550     //!   Linear O(N).
~varray()551     ~varray()
552     {
553         namespace sv = varray_detail;
554         sv::destroy(this->begin(), this->end());
555     }
556 
557     //! @brief Swaps contents of the other varray and this one.
558     //!
559     //! @param other    The varray which content will be swapped with this one's content.
560     //!
561     //! @par Throws
562     //!   @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws,
563     //!   @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws,
564     //! @internal
565     //!   @li It throws only if \c use_memop_in_swap_and_move and \c use_optimized_swap are \c false_type - default.
566     //! @endinternal
567     //!
568     //! @par Complexity
569     //!   Linear O(N).
swap(varray & other)570     void swap(varray & other)
571     {
572         typedef typename
573         vt::use_optimized_swap use_optimized_swap;
574 
575         this->swap_dispatch(other, use_optimized_swap());
576     }
577 
578     //! @pre <tt>other.size() <= capacity() && size() <= other.capacity()</tt>
579     //!
580     //! @brief Swaps contents of the other varray and this one.
581     //!
582     //! @param other    The varray which content will be swapped with this one's content.
583     //!
584     //! @par Throws
585     //!   @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws,
586     //!   @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws,
587     //! @internal
588     //!   @li It throws only if \c use_memop_in_swap_and_move and \c use_optimized_swap are \c false_type - default.
589     //! @endinternal
590     //! @internal
591     //!   @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
592     //! @endinternal
593     //!
594     //! @par Complexity
595     //!   Linear O(N).
596     template <std::size_t C, typename S>
swap(varray<value_type,C,S> & other)597     void swap(varray<value_type, C, S> & other)
598     {
599         errh::check_capacity(*this, other.size());
600         errh::check_capacity(other, this->size());
601 
602         typedef typename
603         vt::use_optimized_swap use_optimized_swap;
604 
605         this->swap_dispatch(other, use_optimized_swap());
606     }
607 
608     //! @pre <tt>count <= capacity()</tt>
609     //!
610     //! @brief Inserts or erases elements at the end such that
611     //!   the size becomes count. New elements are value initialized.
612     //!
613     //! @param count    The number of elements which will be stored in the container.
614     //!
615     //! @par Throws
616     //!   If Value's value initialization throws.
617     //! @internal
618     //!   @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
619     //! @endinternal
620     //!
621     //! @par Complexity
622     //!   Linear O(N).
resize(size_type count)623     void resize(size_type count)
624     {
625         namespace sv = varray_detail;
626         typedef typename vt::disable_trivial_init dti;
627 
628         if ( count < m_size )
629         {
630             sv::destroy(this->begin() + count, this->end());
631         }
632         else
633         {
634             errh::check_capacity(*this, count);                                     // may throw
635 
636             sv::uninitialized_fill(this->end(), this->begin() + count, dti()); // may throw
637         }
638         m_size = count; // update end
639     }
640 
641     //! @pre <tt>count <= capacity()</tt>
642     //!
643     //! @brief Inserts or erases elements at the end such that
644     //!   the size becomes count. New elements are copy constructed from value.
645     //!
646     //! @param count    The number of elements which will be stored in the container.
647     //! @param value    The value used to copy construct the new element.
648     //!
649     //! @par Throws
650     //!   If Value's copy constructor throws.
651     //! @internal
652     //!   @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
653     //! @endinternal
654     //!
655     //! @par Complexity
656     //!   Linear O(N).
resize(size_type count,value_type const & value)657     void resize(size_type count, value_type const& value)
658     {
659         if ( count < m_size )
660         {
661             namespace sv = varray_detail;
662             sv::destroy(this->begin() + count, this->end());
663         }
664         else
665         {
666             errh::check_capacity(*this, count);                                     // may throw
667 
668             std::uninitialized_fill(this->end(), this->begin() + count, value);     // may throw
669         }
670         m_size = count; // update end
671     }
672 
673     //! @pre <tt>count <= capacity()</tt>
674     //!
675     //! @brief This call has no effect because the Capacity of this container is constant.
676     //!
677     //! @param count    The number of elements which the container should be able to contain.
678     //!
679     //! @par Throws
680     //!   Nothing.
681     //! @internal
682     //!   @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
683     //! @endinternal
684     //!
685     //! @par Complexity
686     //!   Linear O(N).
reserve(size_type count)687     void reserve(size_type count)
688     {
689         errh::check_capacity(*this, count);                                         // may throw
690     }
691 
692     //! @pre <tt>size() < capacity()</tt>
693     //!
694     //! @brief Adds a copy of value at the end.
695     //!
696     //! @param value    The value used to copy construct the new element.
697     //!
698     //! @par Throws
699     //!   If Value's copy constructor throws.
700     //! @internal
701     //!   @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
702     //! @endinternal
703     //!
704     //! @par Complexity
705     //!   Constant O(1).
push_back(value_type const & value)706     void push_back(value_type const& value)
707     {
708         typedef typename vt::disable_trivial_init dti;
709 
710         errh::check_capacity(*this, m_size + 1);                                    // may throw
711 
712         namespace sv = varray_detail;
713         sv::construct(dti(), this->end(), value);                                          // may throw
714         ++m_size; // update end
715     }
716 
717     //! @pre <tt>size() < capacity()</tt>
718     //!
719     //! @brief Moves value to the end.
720     //!
721     //! @param value    The value to move construct the new element.
722     //!
723     //! @par Throws
724     //!   If Value's move constructor throws.
725     //! @internal
726     //!   @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
727     //! @endinternal
728     //!
729     //! @par Complexity
730     //!   Constant O(1).
push_back(BOOST_RV_REF (value_type)value)731     void push_back(BOOST_RV_REF(value_type) value)
732     {
733         typedef typename vt::disable_trivial_init dti;
734 
735         errh::check_capacity(*this, m_size + 1);                                    // may throw
736 
737         namespace sv = varray_detail;
738         sv::construct(dti(), this->end(), ::boost::move(value));                                          // may throw
739         ++m_size; // update end
740     }
741 
742     //! @pre <tt>!empty()</tt>
743     //!
744     //! @brief Destroys last value and decreases the size.
745     //!
746     //! @par Throws
747     //!   Nothing by default.
748     //!
749     //! @par Complexity
750     //!   Constant O(1).
pop_back()751     void pop_back()
752     {
753         errh::check_empty(*this);
754 
755         namespace sv = varray_detail;
756         sv::destroy(this->end() - 1);
757         --m_size; // update end
758     }
759 
760     //! @pre
761     //!  @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
762     //!  @li <tt>size() < capacity()</tt>
763     //!
764     //! @brief Inserts a copy of element at position.
765     //!
766     //! @param position    The position at which the new value will be inserted.
767     //! @param value       The value used to copy construct the new element.
768     //!
769     //! @par Throws
770     //!   @li If Value's copy constructor or copy assignment throws
771     //!   @li If Value's move constructor or move assignment throws.
772     //! @internal
773     //!   @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
774     //! @endinternal
775     //!
776     //! @par Complexity
777     //!   Constant or linear.
insert(iterator position,value_type const & value)778     iterator insert(iterator position, value_type const& value)
779     {
780         return this->priv_insert(position, value);
781     }
782 
783     //! @pre
784     //!  @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
785     //!  @li <tt>size() < capacity()</tt>
786     //!
787     //! @brief Inserts a move-constructed element at position.
788     //!
789     //! @param position    The position at which the new value will be inserted.
790     //! @param value       The value used to move construct the new element.
791     //!
792     //! @par Throws
793     //!   If Value's move constructor or move assignment throws.
794     //! @internal
795     //!   @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
796     //! @endinternal
797     //!
798     //! @par Complexity
799     //!   Constant or linear.
insert(iterator position,BOOST_RV_REF (value_type)value)800     iterator insert(iterator position, BOOST_RV_REF(value_type) value)
801     {
802         return this->priv_insert(position, boost::move(value));
803     }
804 
805     //! @pre
806     //!  @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
807     //!  @li <tt>size() + count <= capacity()</tt>
808     //!
809     //! @brief Inserts a count copies of value at position.
810     //!
811     //! @param position    The position at which new elements will be inserted.
812     //! @param count       The number of new elements which will be inserted.
813     //! @param value       The value used to copy construct new elements.
814     //!
815     //! @par Throws
816     //!   @li If Value's copy constructor or copy assignment throws.
817     //!   @li If Value's move constructor or move assignment throws.
818     //! @internal
819     //!   @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
820     //! @endinternal
821     //!
822     //! @par Complexity
823     //!   Linear O(N).
insert(iterator position,size_type count,value_type const & value)824     iterator insert(iterator position, size_type count, value_type const& value)
825     {
826         errh::check_iterator_end_eq(*this, position);
827         errh::check_capacity(*this, m_size + count);                                // may throw
828 
829         if ( position == this->end() )
830         {
831             std::uninitialized_fill(position, position + count, value);             // may throw
832             m_size += count; // update end
833         }
834         else
835         {
836             namespace sv = varray_detail;
837 
838             difference_type to_move = boost::container::iterator_distance(position, this->end());
839 
840             // TODO - should following lines check for exception and revert to the old size?
841 
842             if ( count < static_cast<size_type>(to_move) )
843             {
844                 sv::uninitialized_move(this->end() - count, this->end(), this->end());          // may throw
845                 m_size += count; // update end
846                 sv::move_backward(position, position + to_move - count, this->end() - count);   // may throw
847                 std::fill_n(position, count, value);                                            // may throw
848             }
849             else
850             {
851                 std::uninitialized_fill(this->end(), position + count, value);                  // may throw
852                 m_size += count - to_move; // update end
853                 sv::uninitialized_move(position, position + to_move, position + count);         // may throw
854                 m_size += to_move; // update end
855                 std::fill_n(position, to_move, value);                                          // may throw
856             }
857         }
858 
859         return position;
860     }
861 
862     //! @pre
863     //!  @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
864     //!  @li <tt>distance(first, last) <= capacity()</tt>
865     //!  @li \c Iterator must meet the \c ForwardIterator.
866     //!
867     //! @brief Inserts a copy of a range <tt>[first, last)</tt> at position.
868     //!
869     //! @param position    The position at which new elements will be inserted.
870     //! @param first       The iterator to the first element of a range used to construct new elements.
871     //! @param last        The iterator to the one after the last element of a range used to construct new elements.
872     //!
873     //! @par Throws
874     //!   @li If Value's constructor and assignment taking a dereferenced \c Iterator.
875     //!   @li If Value's move constructor or move assignment throws.
876     //! @internal
877     //!   @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
878     //! @endinternal
879     //!
880     //! @par Complexity
881     //!   Linear O(N).
882     template <typename Iterator>
insert(iterator position,Iterator first,Iterator last)883     iterator insert(iterator position, Iterator first, Iterator last)
884     {
885         this->insert_dispatch(position, first, last);
886         return position;
887     }
888 
889     //! @pre \c position must be a valid iterator of \c *this in range <tt>[begin(), end())</tt>
890     //!
891     //! @brief Erases Value from position.
892     //!
893     //! @param position    The position of the element which will be erased from the container.
894     //!
895     //! @par Throws
896     //!   If Value's move assignment throws.
897     //!
898     //! @par Complexity
899     //!   Linear O(N).
erase(iterator position)900     iterator erase(iterator position)
901     {
902         namespace sv = varray_detail;
903 
904         errh::check_iterator_end_neq(*this, position);
905 
906         //TODO - add empty check?
907         //errh::check_empty(*this);
908 
909         sv::move(position + 1, this->end(), position);                              // may throw
910         sv::destroy(this->end() - 1);
911         --m_size;
912 
913         return position;
914     }
915 
916     //! @pre
917     //!  @li \c first and \c last must define a valid range
918     //!  @li iterators must be in range <tt>[begin(), end()]</tt>
919     //!
920     //! @brief Erases Values from a range <tt>[first, last)</tt>.
921     //!
922     //! @param first    The position of the first element of a range which will be erased from the container.
923     //! @param last     The position of the one after the last element of a range which will be erased from the container.
924     //!
925     //! @par Throws
926     //!   If Value's move assignment throws.
927     //!
928     //! @par Complexity
929     //!   Linear O(N).
erase(iterator first,iterator last)930     iterator erase(iterator first, iterator last)
931     {
932         namespace sv = varray_detail;
933 
934         errh::check_iterator_end_eq(*this, first);
935         errh::check_iterator_end_eq(*this, last);
936 
937         difference_type n = boost::container::iterator_distance(first, last);
938 
939         //TODO - add invalid range check?
940         //BOOST_ASSERT_MSG(0 <= n, "invalid range");
941         //TODO - add this->size() check?
942         //BOOST_ASSERT_MSG(n <= this->size(), "invalid range");
943 
944         sv::move(last, this->end(), first);                                         // may throw
945         sv::destroy(this->end() - n, this->end());
946         m_size -= n;
947 
948         return first;
949     }
950 
951     //! @pre <tt>distance(first, last) <= capacity()</tt>
952     //!
953     //! @brief Assigns a range <tt>[first, last)</tt> of Values to this container.
954     //!
955     //! @param first       The iterator to the first element of a range used to construct new content of this container.
956     //! @param last        The iterator to the one after the last element of a range used to construct new content of this container.
957     //!
958     //! @par Throws
959     //!   If Value's copy constructor or copy assignment throws,
960     //!
961     //! @par Complexity
962     //!   Linear O(N).
963     template <typename Iterator>
assign(Iterator first,Iterator last)964     void assign(Iterator first, Iterator last)
965     {
966         this->assign_dispatch(first, last);                            // may throw
967     }
968 
969     //! @pre <tt>count <= capacity()</tt>
970     //!
971     //! @brief Assigns a count copies of value to this container.
972     //!
973     //! @param count       The new number of elements which will be container in the container.
974     //! @param value       The value which will be used to copy construct the new content.
975     //!
976     //! @par Throws
977     //!   If Value's copy constructor or copy assignment throws.
978     //!
979     //! @par Complexity
980     //!   Linear O(N).
assign(size_type count,value_type const & value)981     void assign(size_type count, value_type const& value)
982     {
983         if ( count < m_size )
984         {
985             namespace sv = varray_detail;
986 
987             std::fill_n(this->begin(), count, value);                               // may throw
988             sv::destroy(this->begin() + count, this->end());
989         }
990         else
991         {
992             errh::check_capacity(*this, count);                                     // may throw
993 
994             std::fill_n(this->begin(), m_size, value);                              // may throw
995             std::uninitialized_fill(this->end(), this->begin() + count, value);     // may throw
996         }
997         m_size = count; // update end
998     }
999 
1000 #if !defined(BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE)
1001 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1002     //! @pre <tt>size() < capacity()</tt>
1003     //!
1004     //! @brief Inserts a Value constructed with
1005     //!   \c std::forward<Args>(args)... in the end of the container.
1006     //!
1007     //! @param args     The arguments of the constructor of the new element which will be created at the end of the container.
1008     //!
1009     //! @par Throws
1010     //!   If in-place constructor throws or Value's move constructor throws.
1011     //! @internal
1012     //!   @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
1013     //! @endinternal
1014     //!
1015     //! @par Complexity
1016     //!   Constant O(1).
1017     template<class ...Args>
emplace_back(BOOST_FWD_REF (Args)...args)1018     void emplace_back(BOOST_FWD_REF(Args) ...args)
1019     {
1020         typedef typename vt::disable_trivial_init dti;
1021 
1022         errh::check_capacity(*this, m_size + 1);                                    // may throw
1023 
1024         namespace sv = varray_detail;
1025         sv::construct(dti(), this->end(), ::boost::forward<Args>(args)...);                // may throw
1026         ++m_size; // update end
1027     }
1028 
1029     //! @pre
1030     //!  @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>
1031     //!  @li <tt>size() < capacity()</tt>
1032     //!
1033     //! @brief Inserts a Value constructed with
1034     //!   \c std::forward<Args>(args)... before position
1035     //!
1036     //! @param position The position at which new elements will be inserted.
1037     //! @param args     The arguments of the constructor of the new element.
1038     //!
1039     //! @par Throws
1040     //!   If in-place constructor throws or if Value's move constructor or move assignment throws.
1041     //! @internal
1042     //!   @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
1043     //! @endinternal
1044     //!
1045     //! @par Complexity
1046     //!   Constant or linear.
1047     template<class ...Args>
emplace(iterator position,BOOST_FWD_REF (Args)...args)1048     iterator emplace(iterator position, BOOST_FWD_REF(Args) ...args)
1049     {
1050         typedef typename vt::disable_trivial_init dti;
1051 
1052         namespace sv = varray_detail;
1053 
1054         errh::check_iterator_end_eq(*this, position);
1055         errh::check_capacity(*this, m_size + 1);                                    // may throw
1056 
1057         if ( position == this->end() )
1058         {
1059             sv::construct(dti(), position, ::boost::forward<Args>(args)...);               // may throw
1060             ++m_size; // update end
1061         }
1062         else
1063         {
1064             // TODO - should following lines check for exception and revert to the old size?
1065 
1066             // TODO - should move be used only if it's nonthrowing?
1067             value_type & r = *(this->end() - 1);
1068             sv::construct(dti(), this->end(), boost::move(r));                             // may throw
1069             ++m_size; // update end
1070             sv::move_backward(position, this->end() - 2, this->end() - 1);          // may throw
1071 
1072             typename aligned_storage
1073                <sizeof(value_type), alignment_of<value_type>::value>::type temp_storage;
1074             value_type * val_p = static_cast<value_type*>(static_cast<void*>(&temp_storage));
1075             sv::construct(dti(), val_p, ::boost::forward<Args>(args)...);                  // may throw
1076             sv::scoped_destructor<value_type> d(val_p);
1077             sv::assign(position, ::boost::move(*val_p));                            // may throw
1078         }
1079 
1080         return position;
1081     }
1082 
1083 #else //  !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || BOOST_CONTAINER_DOXYGEN_INVOKED
1084 
1085    #define BOOST_CONTAINER_VARRAY_EMPLACE_CODE(N) \
1086    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1087    void emplace_back(BOOST_MOVE_UREF##N)\
1088    {\
1089       typedef typename vt::disable_trivial_init dti;\
1090       errh::check_capacity(*this, m_size + 1);/*may throw*/\
1091       \
1092       namespace sv = varray_detail;\
1093       sv::construct(dti(), this->end() BOOST_MOVE_I##N BOOST_MOVE_FWD##N ); /*may throw*/\
1094       ++m_size; /*update end*/\
1095    }\
1096    \
1097    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1098    iterator emplace(iterator position BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1099    {\
1100       typedef typename vt::disable_trivial_init dti;\
1101       namespace sv = varray_detail;\
1102       errh::check_iterator_end_eq(*this, position);\
1103       errh::check_capacity(*this, m_size + 1); /*may throw*/\
1104       if ( position == this->end() ){\
1105          sv::construct(dti(), position BOOST_MOVE_I##N BOOST_MOVE_FWD##N ); /*may throw*/\
1106          ++m_size; /*update end*/\
1107       }\
1108       else{\
1109          /* TODO - should following lines check for exception and revert to the old size? */\
1110          /* TODO - should move be used only if it's nonthrowing? */\
1111          value_type & r = *(this->end() - 1);\
1112          sv::construct(dti(), this->end(), boost::move(r));/*may throw*/\
1113          ++m_size; /*update end*/\
1114          sv::move_backward(position, this->end() - 2, this->end() - 1);/*may throw*/\
1115          typename aligned_storage\
1116             <sizeof(value_type), alignment_of<value_type>::value>::type temp_storage;\
1117          value_type * val_p = static_cast<value_type*>(static_cast<void*>(&temp_storage));\
1118          sv::construct(dti(), val_p BOOST_MOVE_I##N BOOST_MOVE_FWD##N ); /*may throw*/\
1119          sv::scoped_destructor<value_type> d(val_p);\
1120          sv::assign(position, ::boost::move(*val_p));/*may throw*/\
1121       }\
1122       return position;\
1123    }\
1124    BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_VARRAY_EMPLACE_CODE)
1125    #undef BOOST_CONTAINER_VARRAY_EMPLACE_CODE
1126 
1127 #endif //  !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || BOOST_CONTAINER_DOXYGEN_INVOKED
1128 #endif // !BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE
1129 
1130     //! @brief Removes all elements from the container.
1131     //!
1132     //! @par Throws
1133     //!   Nothing.
1134     //!
1135     //! @par Complexity
1136     //!   Constant O(1).
clear()1137     void clear()
1138     {
1139         namespace sv = varray_detail;
1140         sv::destroy(this->begin(), this->end());
1141         m_size = 0; // update end
1142     }
1143 
1144     //! @pre <tt>i < size()</tt>
1145     //!
1146     //! @brief Returns reference to the i-th element.
1147     //!
1148     //! @param i    The element's index.
1149     //!
1150     //! @return reference to the i-th element
1151     //!   from the beginning of the container.
1152     //!
1153     //! @par Throws
1154     //!   \c std::out_of_range exception by default.
1155     //!
1156     //! @par Complexity
1157     //!   Constant O(1).
at(size_type i)1158     reference at(size_type i)
1159     {
1160         errh::check_at(*this, i);                                   // may throw
1161         return *(this->begin() + i);
1162     }
1163 
1164     //! @pre <tt>i < size()</tt>
1165     //!
1166     //! @brief Returns const reference to the i-th element.
1167     //!
1168     //! @param i    The element's index.
1169     //!
1170     //! @return const reference to the i-th element
1171     //!   from the beginning of the container.
1172     //!
1173     //! @par Throws
1174     //!   \c std::out_of_range exception by default.
1175     //!
1176     //! @par Complexity
1177     //!   Constant O(1).
at(size_type i) const1178     const_reference at(size_type i) const
1179     {
1180         errh::check_at(*this, i);                                   // may throw
1181         return *(this->begin() + i);
1182     }
1183 
1184     //! @pre <tt>i < size()</tt>
1185     //!
1186     //! @brief Returns reference to the i-th element.
1187     //!
1188     //! @param i    The element's index.
1189     //!
1190     //! @return reference to the i-th element
1191     //!   from the beginning of the container.
1192     //!
1193     //! @par Throws
1194     //!   Nothing by default.
1195     //!
1196     //! @par Complexity
1197     //!   Constant O(1).
operator [](size_type i)1198     reference operator[](size_type i)
1199     {
1200         // TODO: Remove bounds check? std::vector and std::array operator[] don't check.
1201         errh::check_operator_brackets(*this, i);
1202         return *(this->begin() + i);
1203     }
1204 
1205     //! @pre <tt>i < size()</tt>
1206     //!
1207     //! @brief Returns const reference to the i-th element.
1208     //!
1209     //! @param i    The element's index.
1210     //!
1211     //! @return const reference to the i-th element
1212     //!   from the beginning of the container.
1213     //!
1214     //! @par Throws
1215     //!   Nothing by default.
1216     //!
1217     //! @par Complexity
1218     //!   Constant O(1).
operator [](size_type i) const1219     const_reference operator[](size_type i) const
1220     {
1221         errh::check_operator_brackets(*this, i);
1222         return *(this->begin() + i);
1223     }
1224 
1225     //! @pre \c !empty()
1226     //!
1227     //! @brief Returns reference to the first element.
1228     //!
1229     //! @return reference to the first element
1230     //!   from the beginning of the container.
1231     //!
1232     //! @par Throws
1233     //!   Nothing by default.
1234     //!
1235     //! @par Complexity
1236     //!   Constant O(1).
front()1237     reference front()
1238     {
1239         errh::check_empty(*this);
1240         return *(this->begin());
1241     }
1242 
1243     //! @pre \c !empty()
1244     //!
1245     //! @brief Returns const reference to the first element.
1246     //!
1247     //! @return const reference to the first element
1248     //!   from the beginning of the container.
1249     //!
1250     //! @par Throws
1251     //!   Nothing by default.
1252     //!
1253     //! @par Complexity
1254     //!   Constant O(1).
front() const1255     const_reference front() const
1256     {
1257         errh::check_empty(*this);
1258         return *(this->begin());
1259     }
1260 
1261     //! @pre \c !empty()
1262     //!
1263     //! @brief Returns reference to the last element.
1264     //!
1265     //! @return reference to the last element
1266     //!   from the beginning of the container.
1267     //!
1268     //! @par Throws
1269     //!   Nothing by default.
1270     //!
1271     //! @par Complexity
1272     //!   Constant O(1).
back()1273     reference back()
1274     {
1275         errh::check_empty(*this);
1276         return *(this->end() - 1);
1277     }
1278 
1279     //! @pre \c !empty()
1280     //!
1281     //! @brief Returns const reference to the first element.
1282     //!
1283     //! @return const reference to the last element
1284     //!   from the beginning of the container.
1285     //!
1286     //! @par Throws
1287     //!   Nothing by default.
1288     //!
1289     //! @par Complexity
1290     //!   Constant O(1).
back() const1291     const_reference back() const
1292     {
1293         errh::check_empty(*this);
1294         return *(this->end() - 1);
1295     }
1296 
1297     //! @brief Pointer such that <tt>[data(), data() + size())</tt> is a valid range.
1298     //!   For a non-empty vector <tt>data() == &front()</tt>.
1299     //!
1300     //! @par Throws
1301     //!   Nothing.
1302     //!
1303     //! @par Complexity
1304     //!   Constant O(1).
data()1305     Value * data()
1306     {
1307         return (addressof)(*(this->ptr()));
1308     }
1309 
1310     //! @brief Const pointer such that <tt>[data(), data() + size())</tt> is a valid range.
1311     //!   For a non-empty vector <tt>data() == &front()</tt>.
1312     //!
1313     //! @par Throws
1314     //!   Nothing.
1315     //!
1316     //! @par Complexity
1317     //!   Constant O(1).
data() const1318     const Value * data() const
1319     {
1320         return (addressof)(*(this->ptr()));
1321     }
1322 
1323 
1324     //! @brief Returns iterator to the first element.
1325     //!
1326     //! @return iterator to the first element contained in the vector.
1327     //!
1328     //! @par Throws
1329     //!   Nothing.
1330     //!
1331     //! @par Complexity
1332     //!   Constant O(1).
begin()1333     iterator begin() { return this->ptr(); }
1334 
1335     //! @brief Returns const iterator to the first element.
1336     //!
1337     //! @return const_iterator to the first element contained in the vector.
1338     //!
1339     //! @par Throws
1340     //!   Nothing.
1341     //!
1342     //! @par Complexity
1343     //!   Constant O(1).
begin() const1344     const_iterator begin() const { return this->ptr(); }
1345 
1346     //! @brief Returns const iterator to the first element.
1347     //!
1348     //! @return const_iterator to the first element contained in the vector.
1349     //!
1350     //! @par Throws
1351     //!   Nothing.
1352     //!
1353     //! @par Complexity
1354     //!   Constant O(1).
cbegin() const1355     const_iterator cbegin() const { return this->ptr(); }
1356 
1357     //! @brief Returns iterator to the one after the last element.
1358     //!
1359     //! @return iterator pointing to the one after the last element contained in the vector.
1360     //!
1361     //! @par Throws
1362     //!   Nothing.
1363     //!
1364     //! @par Complexity
1365     //!   Constant O(1).
end()1366     iterator end() { return this->begin() + m_size; }
1367 
1368     //! @brief Returns const iterator to the one after the last element.
1369     //!
1370     //! @return const_iterator pointing to the one after the last element contained in the vector.
1371     //!
1372     //! @par Throws
1373     //!   Nothing.
1374     //!
1375     //! @par Complexity
1376     //!   Constant O(1).
end() const1377     const_iterator end() const { return this->begin() + m_size; }
1378 
1379     //! @brief Returns const iterator to the one after the last element.
1380     //!
1381     //! @return const_iterator pointing to the one after the last element contained in the vector.
1382     //!
1383     //! @par Throws
1384     //!   Nothing.
1385     //!
1386     //! @par Complexity
1387     //!   Constant O(1).
cend() const1388     const_iterator cend() const { return this->cbegin() + m_size; }
1389 
1390     //! @brief Returns reverse iterator to the first element of the reversed container.
1391     //!
1392     //! @return reverse_iterator pointing to the beginning
1393     //! of the reversed varray.
1394     //!
1395     //! @par Throws
1396     //!   Nothing.
1397     //!
1398     //! @par Complexity
1399     //!   Constant O(1).
rbegin()1400     reverse_iterator rbegin() { return reverse_iterator(this->end()); }
1401 
1402     //! @brief Returns const reverse iterator to the first element of the reversed container.
1403     //!
1404     //! @return const_reverse_iterator pointing to the beginning
1405     //! of the reversed varray.
1406     //!
1407     //! @par Throws
1408     //!   Nothing.
1409     //!
1410     //! @par Complexity
1411     //!   Constant O(1).
rbegin() const1412     const_reverse_iterator rbegin() const { return reverse_iterator(this->end()); }
1413 
1414     //! @brief Returns const reverse iterator to the first element of the reversed container.
1415     //!
1416     //! @return const_reverse_iterator pointing to the beginning
1417     //! of the reversed varray.
1418     //!
1419     //! @par Throws
1420     //!   Nothing.
1421     //!
1422     //! @par Complexity
1423     //!   Constant O(1).
crbegin() const1424     const_reverse_iterator crbegin() const { return reverse_iterator(this->end()); }
1425 
1426     //! @brief Returns reverse iterator to the one after the last element of the reversed container.
1427     //!
1428     //! @return reverse_iterator pointing to the one after the last element
1429     //! of the reversed varray.
1430     //!
1431     //! @par Throws
1432     //!   Nothing.
1433     //!
1434     //! @par Complexity
1435     //!   Constant O(1).
rend()1436     reverse_iterator rend() { return reverse_iterator(this->begin()); }
1437 
1438     //! @brief Returns const reverse iterator to the one after the last element of the reversed container.
1439     //!
1440     //! @return const_reverse_iterator pointing to the one after the last element
1441     //! of the reversed varray.
1442     //!
1443     //! @par Throws
1444     //!   Nothing.
1445     //!
1446     //! @par Complexity
1447     //!   Constant O(1).
rend() const1448     const_reverse_iterator rend() const { return reverse_iterator(this->begin()); }
1449 
1450     //! @brief Returns const reverse iterator to the one after the last element of the reversed container.
1451     //!
1452     //! @return const_reverse_iterator pointing to the one after the last element
1453     //! of the reversed varray.
1454     //!
1455     //! @par Throws
1456     //!   Nothing.
1457     //!
1458     //! @par Complexity
1459     //!   Constant O(1).
crend() const1460     const_reverse_iterator crend() const { return reverse_iterator(this->begin()); }
1461 
1462     //! @brief Returns container's capacity.
1463     //!
1464     //! @return container's capacity.
1465     //!
1466     //! @par Throws
1467     //!   Nothing.
1468     //!
1469     //! @par Complexity
1470     //!   Constant O(1).
capacity()1471     static size_type capacity() { return Capacity; }
1472 
1473     //! @brief Returns container's capacity.
1474     //!
1475     //! @return container's capacity.
1476     //!
1477     //! @par Throws
1478     //!   Nothing.
1479     //!
1480     //! @par Complexity
1481     //!   Constant O(1).
max_size()1482     static size_type max_size() { return Capacity; }
1483 
1484     //! @brief Returns the number of stored elements.
1485     //!
1486     //! @return Number of elements contained in the container.
1487     //!
1488     //! @par Throws
1489     //!   Nothing.
1490     //!
1491     //! @par Complexity
1492     //!   Constant O(1).
size() const1493     size_type size() const { return m_size; }
1494 
1495     //! @brief Queries if the container contains elements.
1496     //!
1497     //! @return true if the number of elements contained in the
1498     //!   container is equal to 0.
1499     //!
1500     //! @par Throws
1501     //!   Nothing.
1502     //!
1503     //! @par Complexity
1504     //!   Constant O(1).
empty() const1505     bool empty() const { return 0 == m_size; }
1506 
1507 private:
1508 
1509     // @par Throws
1510     //   Nothing.
1511     // @par Complexity
1512     //   Linear O(N).
1513     template <std::size_t C, typename S>
move_ctor_dispatch(varray<value_type,C,S> & other,true_type)1514     void move_ctor_dispatch(varray<value_type, C, S> & other, true_type /*use_memop*/)
1515     {
1516         ::memcpy(this->data(), other.data(), sizeof(Value) * other.m_size);
1517         m_size = other.m_size;
1518     }
1519 
1520     // @par Throws
1521     //   @li If boost::has_nothrow_move<Value>::value is true and Value's move constructor throws
1522     //   @li If boost::has_nothrow_move<Value>::value is false and Value's copy constructor throws.
1523     // @par Complexity
1524     //   Linear O(N).
1525     template <std::size_t C, typename S>
move_ctor_dispatch(varray<value_type,C,S> & other,false_type)1526     void move_ctor_dispatch(varray<value_type, C, S> & other, false_type /*use_memop*/)
1527     {
1528         namespace sv = varray_detail;
1529         sv::uninitialized_move_if_noexcept(other.begin(), other.end(), this->begin());                  // may throw
1530         m_size = other.m_size;
1531     }
1532 
1533     // @par Throws
1534     //   Nothing.
1535     // @par Complexity
1536     //   Linear O(N).
1537     template <std::size_t C, typename S>
move_assign_dispatch(varray<value_type,C,S> & other,true_type)1538     void move_assign_dispatch(varray<value_type, C, S> & other, true_type /*use_memop*/)
1539     {
1540         this->clear();
1541 
1542         ::memcpy(this->data(), other.data(), sizeof(Value) * other.m_size);
1543         boost::adl_move_swap(m_size, other.m_size);
1544     }
1545 
1546     // @par Throws
1547     //   @li If boost::has_nothrow_move<Value>::value is true and Value's move constructor or move assignment throws
1548     //   @li If boost::has_nothrow_move<Value>::value is false and Value's copy constructor or move assignment throws.
1549     // @par Complexity
1550     //   Linear O(N).
1551     template <std::size_t C, typename S>
move_assign_dispatch(varray<value_type,C,S> & other,false_type)1552     void move_assign_dispatch(varray<value_type, C, S> & other, false_type /*use_memop*/)
1553     {
1554         namespace sv = varray_detail;
1555         if ( m_size <= static_cast<size_type>(other.size()) )
1556         {
1557             sv::move_if_noexcept(other.begin(), other.begin() + m_size, this->begin());             // may throw
1558             // TODO - perform uninitialized_copy first?
1559             sv::uninitialized_move_if_noexcept(other.begin() + m_size, other.end(), this->end());   // may throw
1560         }
1561         else
1562         {
1563             sv::move_if_noexcept(other.begin(), other.end(), this->begin());                        // may throw
1564             sv::destroy(this->begin() + other.size(), this->end());
1565         }
1566         m_size = other.size(); // update end
1567     }
1568 
1569     // @par Throws
1570     //   Nothing.
1571     // @par Complexity
1572     //   Linear O(N).
1573     template <std::size_t C, typename S>
swap_dispatch(varray<value_type,C,S> & other,true_type const &)1574     void swap_dispatch(varray<value_type, C, S> & other, true_type const& /*use_optimized_swap*/)
1575     {
1576         typedef typename
1577         if_c<
1578             Capacity < C,
1579             aligned_storage_type,
1580             typename varray<value_type, C, S>::aligned_storage_type
1581         >::type
1582         storage_type;
1583 
1584         storage_type temp_storage;
1585         value_type * temp_ptr = static_cast<value_type*>(static_cast<void*>(&temp_storage));
1586 
1587         ::memcpy(temp_ptr, this->data(), sizeof(Value) * this->size());
1588         ::memcpy(this->data(), other.data(), sizeof(Value) * other.size());
1589         ::memcpy(other.data(), temp_ptr, sizeof(Value) * this->size());
1590 
1591         boost::adl_move_swap(m_size, other.m_size);
1592     }
1593 
1594     // @par Throws
1595     //   If Value's move constructor or move assignment throws
1596     //   but only if use_memop_in_swap_and_move is false_type - default.
1597     // @par Complexity
1598     //   Linear O(N).
1599     template <std::size_t C, typename S>
swap_dispatch(varray<value_type,C,S> & other,false_type const &)1600     void swap_dispatch(varray<value_type, C, S> & other, false_type const& /*use_optimized_swap*/)
1601     {
1602         namespace sv = varray_detail;
1603 
1604         typedef typename
1605         vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;
1606 
1607         if ( this->size() < other.size() )
1608             swap_dispatch_impl(this->begin(), this->end(), other.begin(), other.end(), use_memop_in_swap_and_move()); // may throw
1609         else
1610             swap_dispatch_impl(other.begin(), other.end(), this->begin(), this->end(), use_memop_in_swap_and_move()); // may throw
1611         boost::adl_move_swap(m_size, other.m_size);
1612     }
1613 
1614     // @par Throws
1615     //   Nothing.
1616     // @par Complexity
1617     //   Linear O(N).
swap_dispatch_impl(iterator first_sm,iterator last_sm,iterator first_la,iterator last_la,true_type const &)1618     void swap_dispatch_impl(iterator first_sm, iterator last_sm, iterator first_la, iterator last_la, true_type const& /*use_memop*/)
1619     {
1620         //BOOST_ASSERT_MSG(boost::container::iterator_distance(first_sm, last_sm) <= boost::container::iterator_distance(first_la, last_la));
1621 
1622         namespace sv = varray_detail;
1623         for (; first_sm != last_sm ; ++first_sm, ++first_la)
1624         {
1625             typename aligned_storage<
1626                 sizeof(value_type),
1627                 alignment_of<value_type>::value
1628             >::type temp_storage;
1629             value_type * temp_ptr = static_cast<value_type*>(static_cast<void*>(&temp_storage));
1630             ::memcpy(temp_ptr, (addressof)(*first_sm), sizeof(value_type));
1631             ::memcpy((addressof)(*first_sm), (addressof)(*first_la), sizeof(value_type));
1632             ::memcpy((addressof)(*first_la), temp_ptr, sizeof(value_type));
1633         }
1634 
1635         ::memcpy(first_sm, first_la, sizeof(value_type) * boost::container::iterator_distance(first_la, last_la));
1636     }
1637 
1638     // @par Throws
1639     //   If Value's move constructor or move assignment throws.
1640     // @par Complexity
1641     //   Linear O(N).
swap_dispatch_impl(iterator first_sm,iterator last_sm,iterator first_la,iterator last_la,false_type const &)1642     void swap_dispatch_impl(iterator first_sm, iterator last_sm, iterator first_la, iterator last_la, false_type const& /*use_memop*/)
1643     {
1644         //BOOST_ASSERT_MSG(boost::container::iterator_distance(first_sm, last_sm) <= boost::container::iterator_distance(first_la, last_la));
1645 
1646         namespace sv = varray_detail;
1647         for (; first_sm != last_sm ; ++first_sm, ++first_la)
1648         {
1649             //boost::adl_move_swap(*first_sm, *first_la);                                    // may throw
1650             value_type temp(boost::move(*first_sm));                                // may throw
1651             *first_sm = boost::move(*first_la);                                     // may throw
1652             *first_la = boost::move(temp);                                          // may throw
1653         }
1654         sv::uninitialized_move(first_la, last_la, first_sm);                        // may throw
1655         sv::destroy(first_la, last_la);
1656     }
1657 
1658     // insert
1659 
1660     // @par Throws
1661     //   If Value's move constructor or move assignment throws
1662     //   or if Value's copy assignment throws.
1663     // @par Complexity
1664     //   Linear O(N).
1665     template <typename V>
priv_insert(iterator position,V & value)1666     iterator priv_insert(iterator position, V & value)
1667     {
1668         typedef typename vt::disable_trivial_init dti;
1669         namespace sv = varray_detail;
1670 
1671         errh::check_iterator_end_eq(*this, position);
1672         errh::check_capacity(*this, m_size + 1);                                    // may throw
1673 
1674         if ( position == this->end() )
1675         {
1676             sv::construct(dti(), position, value);                                         // may throw
1677             ++m_size; // update end
1678         }
1679         else
1680         {
1681             // TODO - should following lines check for exception and revert to the old size?
1682 
1683             // TODO - should move be used only if it's nonthrowing?
1684             value_type & r = *(this->end() - 1);
1685             sv::construct(dti(), this->end(), boost::move(r));                             // may throw
1686             ++m_size; // update end
1687             sv::move_backward(position, this->end() - 2, this->end() - 1);          // may throw
1688             sv::assign(position, value);                                            // may throw
1689         }
1690 
1691         return position;
1692     }
1693 
1694     // insert
1695 
1696     // @par Throws
1697     //   If Value's move constructor, move assignment throws
1698     //   or if Value's copy constructor or copy assignment throws.
1699     // @par Complexity
1700     //   Linear O(N).
1701     template <typename Iterator>
1702     typename iterator_enable_if_tag<Iterator, std::random_access_iterator_tag>::type
insert_dispatch(iterator position,Iterator first,Iterator last)1703        insert_dispatch(iterator position, Iterator first, Iterator last)
1704     {
1705         errh::check_iterator_end_eq(*this, position);
1706 
1707         size_type count = boost::container::iterator_distance(first, last);
1708 
1709         errh::check_capacity(*this, m_size + count);                                             // may throw
1710 
1711         if ( position == this->end() )
1712         {
1713             namespace sv = varray_detail;
1714 
1715             sv::uninitialized_copy(first, last, position);                                      // may throw
1716             m_size += count; // update end
1717         }
1718         else
1719         {
1720             this->insert_in_the_middle(position, first, last, count);                           // may throw
1721         }
1722     }
1723 
1724     // @par Throws
1725     //   If Value's move constructor, move assignment throws
1726     //   or if Value's copy constructor or copy assignment throws.
1727     // @par Complexity
1728     //   Linear O(N).
1729     template <typename Iterator, typename Category>
1730     typename iterator_disable_if_tag<Iterator, std::random_access_iterator_tag>::type
insert_dispatch(iterator position,Iterator first,Iterator last)1731         insert_dispatch(iterator position, Iterator first, Iterator last)
1732     {
1733         errh::check_iterator_end_eq(*this, position);
1734 
1735         if ( position == this->end() )
1736         {
1737             namespace sv = varray_detail;
1738 
1739             std::ptrdiff_t d = boost::container::iterator_distance(position, this->begin() + Capacity);
1740             std::size_t count = sv::uninitialized_copy_s(first, last, position, d);                     // may throw
1741 
1742             errh::check_capacity(*this, count <= static_cast<std::size_t>(d) ? m_size + count : Capacity + 1);  // may throw
1743 
1744             m_size += count;
1745         }
1746         else
1747         {
1748             size_type count = boost::container::iterator_distance(first, last);
1749 
1750             errh::check_capacity(*this, m_size + count);                                                // may throw
1751 
1752             this->insert_in_the_middle(position, first, last, count);                                   // may throw
1753         }
1754     }
1755 
1756     // @par Throws
1757     //   If Value's move constructor, move assignment throws
1758     //   or if Value's copy constructor or copy assignment throws.
1759     // @par Complexity
1760     //   Linear O(N).
1761     template <typename Iterator>
insert_in_the_middle(iterator position,Iterator first,Iterator last,difference_type count)1762     void insert_in_the_middle(iterator position, Iterator first, Iterator last, difference_type count)
1763     {
1764         namespace sv = varray_detail;
1765 
1766         difference_type to_move = boost::container::iterator_distance(position, this->end());
1767 
1768         // TODO - should following lines check for exception and revert to the old size?
1769 
1770         if ( count < to_move )
1771         {
1772             sv::uninitialized_move(this->end() - count, this->end(), this->end());              // may throw
1773             m_size += count; // update end
1774             sv::move_backward(position, position + to_move - count, this->end() - count);       // may throw
1775             sv::copy(first, last, position);                                                    // may throw
1776         }
1777         else
1778         {
1779             Iterator middle_iter = first;
1780             boost::container::iterator_advance(middle_iter, to_move);
1781 
1782             sv::uninitialized_copy(middle_iter, last, this->end());                             // may throw
1783             m_size += count - to_move; // update end
1784             sv::uninitialized_move(position, position + to_move, position + count);             // may throw
1785             m_size += to_move; // update end
1786             sv::copy(first, middle_iter, position);                                             // may throw
1787         }
1788     }
1789 
1790     // assign
1791 
1792     // @par Throws
1793     //   If Value's constructor or assignment taking dereferenced Iterator throws.
1794     // @par Complexity
1795     //   Linear O(N).
1796     template <typename Iterator>
1797     typename iterator_enable_if_tag<Iterator, std::random_access_iterator_tag>::type
assign_dispatch(Iterator first,Iterator last)1798        assign_dispatch(Iterator first, Iterator last)
1799     {
1800         namespace sv = varray_detail;
1801 
1802         size_type s = boost::container::iterator_distance(first, last);
1803 
1804         errh::check_capacity(*this, s);                                     // may throw
1805 
1806         if ( m_size <= static_cast<size_type>(s) )
1807         {
1808             sv::copy(first, first + m_size, this->begin());                 // may throw
1809             // TODO - perform uninitialized_copy first?
1810             sv::uninitialized_copy(first + m_size, last, this->end());      // may throw
1811         }
1812         else
1813         {
1814             sv::copy(first, last, this->begin());                           // may throw
1815             sv::destroy(this->begin() + s, this->end());
1816         }
1817         m_size = s; // update end
1818     }
1819 
1820     // @par Throws
1821     //   If Value's constructor or assignment taking dereferenced Iterator throws.
1822     // @par Complexity
1823     //   Linear O(N).
1824     template <typename Iterator, typename Category>
1825     typename iterator_disable_if_tag<Iterator, std::random_access_iterator_tag>::type
assign_dispatch(Iterator first,Iterator last)1826        assign_dispatch(Iterator first, Iterator last)
1827     {
1828         namespace sv = varray_detail;
1829 
1830         size_type s = 0;
1831         iterator it = this->begin();
1832 
1833         for ( ; it != this->end() && first != last ; ++it, ++first, ++s )
1834             *it = *first;                                                                                   // may throw
1835 
1836         sv::destroy(it, this->end());
1837 
1838         std::ptrdiff_t d = boost::container::iterator_distance(it, this->begin() + Capacity);
1839         std::size_t count = sv::uninitialized_copy_s(first, last, it, d);                                   // may throw
1840         s += count;
1841 
1842         errh::check_capacity(*this, count <= static_cast<std::size_t>(d) ? s : Capacity + 1);               // may throw
1843 
1844         m_size = s; // update end
1845     }
1846 
ptr()1847     pointer ptr()
1848     {
1849         return pointer(static_cast<Value*>(static_cast<void*>(&m_storage)));
1850     }
1851 
ptr() const1852     const_pointer ptr() const
1853     {
1854         return pointer(static_cast<const Value*>(static_cast<const void*>(&m_storage)));
1855     }
1856 
1857     size_type m_size;
1858     aligned_storage_type m_storage;
1859 };
1860 
1861 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1862 
1863 template<typename Value, typename Strategy>
1864 class varray<Value, 0, Strategy>
1865 {
1866     typedef varray_traits<
1867         Value, 0, Strategy
1868     > vt;
1869 
1870     typedef typename vt::size_type stored_size_type;
1871     typedef typename vt::error_handler errh;
1872 
1873 public:
1874     typedef typename vt::value_type value_type;
1875     typedef stored_size_type size_type;
1876     typedef typename vt::difference_type difference_type;
1877     typedef typename vt::pointer pointer;
1878     typedef typename vt::const_pointer const_pointer;
1879     typedef typename vt::reference reference;
1880     typedef typename vt::const_reference const_reference;
1881 
1882     typedef pointer iterator;
1883     typedef const_pointer const_iterator;
1884     typedef boost::container::reverse_iterator<iterator> reverse_iterator;
1885     typedef boost::container::reverse_iterator<const_iterator> const_reverse_iterator;
1886 
1887     // nothrow
varray()1888     varray() {}
1889 
1890     // strong
varray(size_type count)1891     explicit varray(size_type count)
1892     {
1893         errh::check_capacity(*this, count);                                         // may throw
1894     }
1895 
1896     // strong
varray(size_type count,value_type const &)1897     varray(size_type count, value_type const&)
1898     {
1899         errh::check_capacity(*this, count);                                         // may throw
1900     }
1901 
1902     // strong
varray(varray const & other)1903     varray(varray const& other)
1904     {
1905         errh::check_capacity(*this, other.size());
1906     }
1907 
1908     // strong
1909     template <size_t C, typename S>
varray(varray<value_type,C,S> const & other)1910     varray(varray<value_type, C, S> const& other)
1911     {
1912         errh::check_capacity(*this, other.size());                                  // may throw
1913     }
1914 
1915     // strong
1916     template <typename Iterator>
varray(Iterator first,Iterator last)1917     varray(Iterator first, Iterator last)
1918     {
1919         errh::check_capacity(*this, boost::container::iterator_distance(first, last));                    // may throw
1920     }
1921 
1922     // basic
operator =(varray const & other)1923     varray & operator=(varray const& other)
1924     {
1925         errh::check_capacity(*this, other.size());
1926         return *this;
1927     }
1928 
1929     // basic
1930     template <size_t C, typename S>
operator =(varray<value_type,C,S> const & other)1931     varray & operator=(varray<value_type, C, S> const& other)
1932     {
1933         errh::check_capacity(*this, other.size());                                  // may throw
1934         return *this;
1935     }
1936 
1937     // nothrow
~varray()1938     ~varray() {}
1939 
1940     // strong
resize(size_type count)1941     void resize(size_type count)
1942     {
1943         errh::check_capacity(*this, count);                                         // may throw
1944     }
1945 
1946     // strong
resize(size_type count,value_type const &)1947     void resize(size_type count, value_type const&)
1948     {
1949         errh::check_capacity(*this, count);                                         // may throw
1950     }
1951 
1952 
1953     // nothrow
reserve(size_type count)1954     void reserve(size_type count)
1955     {
1956         errh::check_capacity(*this, count);                                         // may throw
1957     }
1958 
1959     // strong
push_back(value_type const &)1960     void push_back(value_type const&)
1961     {
1962         errh::check_capacity(*this, 1);                                             // may throw
1963     }
1964 
1965     // nothrow
pop_back()1966     void pop_back()
1967     {
1968         errh::check_empty(*this);
1969     }
1970 
1971     // basic
insert(iterator position,value_type const &)1972     void insert(iterator position, value_type const&)
1973     {
1974         errh::check_iterator_end_eq(*this, position);
1975         errh::check_capacity(*this, 1);                                             // may throw
1976     }
1977 
1978     // basic
insert(iterator position,size_type count,value_type const &)1979     void insert(iterator position, size_type count, value_type const&)
1980     {
1981         errh::check_iterator_end_eq(*this, position);
1982         errh::check_capacity(*this, count);                                         // may throw
1983     }
1984 
1985     // basic
1986     template <typename Iterator>
insert(iterator,Iterator first,Iterator last)1987     void insert(iterator, Iterator first, Iterator last)
1988     {
1989         errh::check_capacity(*this, boost::container::iterator_distance(first, last));                    // may throw
1990     }
1991 
1992     // basic
erase(iterator position)1993     void erase(iterator position)
1994     {
1995         errh::check_iterator_end_neq(*this, position);
1996     }
1997 
1998     // basic
erase(iterator first,iterator last)1999     void erase(iterator first, iterator last)
2000     {
2001         errh::check_iterator_end_eq(*this, first);
2002         errh::check_iterator_end_eq(*this, last);
2003 
2004         //BOOST_ASSERT_MSG(0 <= n, "invalid range");
2005     }
2006 
2007     // basic
2008     template <typename Iterator>
assign(Iterator first,Iterator last)2009     void assign(Iterator first, Iterator last)
2010     {
2011         errh::check_capacity(*this, boost::container::iterator_distance(first, last));                    // may throw
2012     }
2013 
2014     // basic
assign(size_type count,value_type const &)2015     void assign(size_type count, value_type const&)
2016     {
2017         errh::check_capacity(*this, count);                                     // may throw
2018     }
2019 
2020     // nothrow
clear()2021     void clear() {}
2022 
2023     // strong
at(size_type i)2024     reference at(size_type i)
2025     {
2026         errh::check_at(*this, i);                                   // may throw
2027         return *(this->begin() + i);
2028     }
2029 
2030     // strong
at(size_type i) const2031     const_reference at(size_type i) const
2032     {
2033         errh::check_at(*this, i);                                   // may throw
2034         return *(this->begin() + i);
2035     }
2036 
2037     // nothrow
operator [](size_type i)2038     reference operator[](size_type i)
2039     {
2040         errh::check_operator_brackets(*this, i);
2041         return *(this->begin() + i);
2042     }
2043 
2044     // nothrow
operator [](size_type i) const2045     const_reference operator[](size_type i) const
2046     {
2047         errh::check_operator_brackets(*this, i);
2048         return *(this->begin() + i);
2049     }
2050 
2051     // nothrow
front()2052     reference front()
2053     {
2054         errh::check_empty(*this);
2055         return *(this->begin());
2056     }
2057 
2058     // nothrow
front() const2059     const_reference front() const
2060     {
2061         errh::check_empty(*this);
2062         return *(this->begin());
2063     }
2064 
2065     // nothrow
back()2066     reference back()
2067     {
2068         errh::check_empty(*this);
2069         return *(this->end() - 1);
2070     }
2071 
2072     // nothrow
back() const2073     const_reference back() const
2074     {
2075         errh::check_empty(*this);
2076         return *(this->end() - 1);
2077     }
2078 
2079     // nothrow
data()2080     Value * data() { return (addressof)(*(this->ptr())); }
data() const2081     const Value * data() const { return (addressof)(*(this->ptr())); }
2082 
2083     // nothrow
begin()2084     iterator begin() { return this->ptr(); }
begin() const2085     const_iterator begin() const { return this->ptr(); }
cbegin() const2086     const_iterator cbegin() const { return this->ptr(); }
end()2087     iterator end() { return this->begin(); }
end() const2088     const_iterator end() const { return this->begin(); }
cend() const2089     const_iterator cend() const { return this->cbegin(); }
2090     // nothrow
rbegin()2091     reverse_iterator rbegin() { return reverse_iterator(this->end()); }
rbegin() const2092     const_reverse_iterator rbegin() const { return reverse_iterator(this->end()); }
crbegin() const2093     const_reverse_iterator crbegin() const { return reverse_iterator(this->end()); }
rend()2094     reverse_iterator rend() { return reverse_iterator(this->begin()); }
rend() const2095     const_reverse_iterator rend() const { return reverse_iterator(this->begin()); }
crend() const2096     const_reverse_iterator crend() const { return reverse_iterator(this->begin()); }
2097 
2098     // nothrow
capacity() const2099     size_type capacity() const { return 0; }
max_size() const2100     size_type max_size() const { return 0; }
size() const2101     size_type size() const { return 0; }
empty() const2102     bool empty() const { return true; }
2103 
2104 private:
2105 
ptr()2106     pointer ptr()
2107     {
2108         return pointer(reinterpret_cast<Value*>(this));
2109     }
2110 
ptr() const2111     const_pointer ptr() const
2112     {
2113         return const_pointer(reinterpret_cast<const Value*>(this));
2114     }
2115 };
2116 
2117 #endif // !BOOST_CONTAINER_DOXYGEN_INVOKED
2118 
2119 //! @brief Checks if contents of two varrays are equal.
2120 //!
2121 //! @ingroup varray_non_member
2122 //!
2123 //! @param x    The first varray.
2124 //! @param y    The second varray.
2125 //!
2126 //! @return     \c true if containers have the same size and elements in both containers are equal.
2127 //!
2128 //! @par Complexity
2129 //!   Linear O(N).
2130 template<typename V, std::size_t C1, typename S1, std::size_t C2, typename S2>
operator ==(varray<V,C1,S1> const & x,varray<V,C2,S2> const & y)2131 bool operator== (varray<V, C1, S1> const& x, varray<V, C2, S2> const& y)
2132 {
2133     return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin());
2134 }
2135 
2136 //! @brief Checks if contents of two varrays are not equal.
2137 //!
2138 //! @ingroup varray_non_member
2139 //!
2140 //! @param x    The first varray.
2141 //! @param y    The second varray.
2142 //!
2143 //! @return     \c true if containers have different size or elements in both containers are not equal.
2144 //!
2145 //! @par Complexity
2146 //!   Linear O(N).
2147 template<typename V, std::size_t C1, typename S1, std::size_t C2, typename S2>
operator !=(varray<V,C1,S1> const & x,varray<V,C2,S2> const & y)2148 bool operator!= (varray<V, C1, S1> const& x, varray<V, C2, S2> const& y)
2149 {
2150     return !(x==y);
2151 }
2152 
2153 //! @brief Lexicographically compares varrays.
2154 //!
2155 //! @ingroup varray_non_member
2156 //!
2157 //! @param x    The first varray.
2158 //! @param y    The second varray.
2159 //!
2160 //! @return     \c true if x compares lexicographically less than y.
2161 //!
2162 //! @par Complexity
2163 //!   Linear O(N).
2164 template<typename V, std::size_t C1, typename S1, std::size_t C2, typename S2>
operator <(varray<V,C1,S1> const & x,varray<V,C2,S2> const & y)2165 bool operator< (varray<V, C1, S1> const& x, varray<V, C2, S2> const& y)
2166 {
2167     return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
2168 }
2169 
2170 //! @brief Lexicographically compares varrays.
2171 //!
2172 //! @ingroup varray_non_member
2173 //!
2174 //! @param x    The first varray.
2175 //! @param y    The second varray.
2176 //!
2177 //! @return     \c true if y compares lexicographically less than x.
2178 //!
2179 //! @par Complexity
2180 //!   Linear O(N).
2181 template<typename V, std::size_t C1, typename S1, std::size_t C2, typename S2>
operator >(varray<V,C1,S1> const & x,varray<V,C2,S2> const & y)2182 bool operator> (varray<V, C1, S1> const& x, varray<V, C2, S2> const& y)
2183 {
2184     return y<x;
2185 }
2186 
2187 //! @brief Lexicographically compares varrays.
2188 //!
2189 //! @ingroup varray_non_member
2190 //!
2191 //! @param x    The first varray.
2192 //! @param y    The second varray.
2193 //!
2194 //! @return     \c true if y don't compare lexicographically less than x.
2195 //!
2196 //! @par Complexity
2197 //!   Linear O(N).
2198 template<typename V, std::size_t C1, typename S1, std::size_t C2, typename S2>
operator <=(varray<V,C1,S1> const & x,varray<V,C2,S2> const & y)2199 bool operator<= (varray<V, C1, S1> const& x, varray<V, C2, S2> const& y)
2200 {
2201     return !(y<x);
2202 }
2203 
2204 //! @brief Lexicographically compares varrays.
2205 //!
2206 //! @ingroup varray_non_member
2207 //!
2208 //! @param x    The first varray.
2209 //! @param y    The second varray.
2210 //!
2211 //! @return     \c true if x don't compare lexicographically less than y.
2212 //!
2213 //! @par Complexity
2214 //!   Linear O(N).
2215 template<typename V, std::size_t C1, typename S1, std::size_t C2, typename S2>
operator >=(varray<V,C1,S1> const & x,varray<V,C2,S2> const & y)2216 bool operator>= (varray<V, C1, S1> const& x, varray<V, C2, S2> const& y)
2217 {
2218     return !(x<y);
2219 }
2220 
2221 //! @brief Swaps contents of two varrays.
2222 //!
2223 //! This function calls varray::swap().
2224 //!
2225 //! @ingroup varray_non_member
2226 //!
2227 //! @param x    The first varray.
2228 //! @param y    The second varray.
2229 //!
2230 //! @par Complexity
2231 //!   Linear O(N).
2232 template<typename V, std::size_t C1, typename S1, std::size_t C2, typename S2>
swap(varray<V,C1,S1> & x,varray<V,C2,S2> & y)2233 inline void swap(varray<V, C1, S1> & x, varray<V, C2, S2> & y)
2234 {
2235     x.swap(y);
2236 }
2237 
2238 }}} // namespace boost::container::dtl
2239 
2240 #include <boost/container/detail/config_end.hpp>
2241 
2242 #endif // BOOST_CONTAINER_DETAIL_VARRAY_HPP
2243