]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/container/bench/detail/varray.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / container / bench / detail / varray.hpp
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
82 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
104 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>
115 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>
122 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>
137 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>
146 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>
153 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>
162 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>
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).
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).
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).
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>
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).
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>
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).
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)
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).
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>
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).
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>
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).
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).
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>
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).
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).
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).
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).
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).
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).
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.
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.
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).
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>
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).
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).
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>
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).
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>
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>
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).
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).
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).
1178 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).
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).
1219 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).
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).
1255 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).
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).
1291 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).
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).
1318 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).
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).
1344 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).
1355 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).
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).
1377 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).
1388 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).
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).
1412 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).
1424 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).
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).
1448 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).
1460 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).
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).
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).
1493 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).
1505 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>
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>
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>
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>
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>
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>
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).
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).
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>
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
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
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>
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
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
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
1847 pointer ptr()
1848 {
1849 return pointer(static_cast<Value*>(static_cast<void*>(&m_storage)));
1850 }
1851
1852 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
1888 varray() {}
1889
1890 // strong
1891 explicit varray(size_type count)
1892 {
1893 errh::check_capacity(*this, count); // may throw
1894 }
1895
1896 // strong
1897 varray(size_type count, value_type const&)
1898 {
1899 errh::check_capacity(*this, count); // may throw
1900 }
1901
1902 // strong
1903 varray(varray const& other)
1904 {
1905 errh::check_capacity(*this, other.size());
1906 }
1907
1908 // strong
1909 template <size_t C, typename S>
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>
1917 varray(Iterator first, Iterator last)
1918 {
1919 errh::check_capacity(*this, boost::container::iterator_distance(first, last)); // may throw
1920 }
1921
1922 // basic
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>
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
1938 ~varray() {}
1939
1940 // strong
1941 void resize(size_type count)
1942 {
1943 errh::check_capacity(*this, count); // may throw
1944 }
1945
1946 // strong
1947 void resize(size_type count, value_type const&)
1948 {
1949 errh::check_capacity(*this, count); // may throw
1950 }
1951
1952
1953 // nothrow
1954 void reserve(size_type count)
1955 {
1956 errh::check_capacity(*this, count); // may throw
1957 }
1958
1959 // strong
1960 void push_back(value_type const&)
1961 {
1962 errh::check_capacity(*this, 1); // may throw
1963 }
1964
1965 // nothrow
1966 void pop_back()
1967 {
1968 errh::check_empty(*this);
1969 }
1970
1971 // basic
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
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>
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
1993 void erase(iterator position)
1994 {
1995 errh::check_iterator_end_neq(*this, position);
1996 }
1997
1998 // basic
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>
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
2015 void assign(size_type count, value_type const&)
2016 {
2017 errh::check_capacity(*this, count); // may throw
2018 }
2019
2020 // nothrow
2021 void clear() {}
2022
2023 // strong
2024 reference at(size_type i)
2025 {
2026 errh::check_at(*this, i); // may throw
2027 return *(this->begin() + i);
2028 }
2029
2030 // strong
2031 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
2038 reference operator[](size_type i)
2039 {
2040 errh::check_operator_brackets(*this, i);
2041 return *(this->begin() + i);
2042 }
2043
2044 // nothrow
2045 const_reference operator[](size_type i) const
2046 {
2047 errh::check_operator_brackets(*this, i);
2048 return *(this->begin() + i);
2049 }
2050
2051 // nothrow
2052 reference front()
2053 {
2054 errh::check_empty(*this);
2055 return *(this->begin());
2056 }
2057
2058 // nothrow
2059 const_reference front() const
2060 {
2061 errh::check_empty(*this);
2062 return *(this->begin());
2063 }
2064
2065 // nothrow
2066 reference back()
2067 {
2068 errh::check_empty(*this);
2069 return *(this->end() - 1);
2070 }
2071
2072 // nothrow
2073 const_reference back() const
2074 {
2075 errh::check_empty(*this);
2076 return *(this->end() - 1);
2077 }
2078
2079 // nothrow
2080 Value * data() { return (addressof)(*(this->ptr())); }
2081 const Value * data() const { return (addressof)(*(this->ptr())); }
2082
2083 // nothrow
2084 iterator begin() { return this->ptr(); }
2085 const_iterator begin() const { return this->ptr(); }
2086 const_iterator cbegin() const { return this->ptr(); }
2087 iterator end() { return this->begin(); }
2088 const_iterator end() const { return this->begin(); }
2089 const_iterator cend() const { return this->cbegin(); }
2090 // nothrow
2091 reverse_iterator rbegin() { return reverse_iterator(this->end()); }
2092 const_reverse_iterator rbegin() const { return reverse_iterator(this->end()); }
2093 const_reverse_iterator crbegin() const { return reverse_iterator(this->end()); }
2094 reverse_iterator rend() { return reverse_iterator(this->begin()); }
2095 const_reverse_iterator rend() const { return reverse_iterator(this->begin()); }
2096 const_reverse_iterator crend() const { return reverse_iterator(this->begin()); }
2097
2098 // nothrow
2099 size_type capacity() const { return 0; }
2100 size_type max_size() const { return 0; }
2101 size_type size() const { return 0; }
2102 bool empty() const { return true; }
2103
2104 private:
2105
2106 pointer ptr()
2107 {
2108 return pointer(reinterpret_cast<Value*>(this));
2109 }
2110
2111 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>
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>
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>
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>
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>
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>
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>
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