[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

array_vector.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 2002-2004 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 #ifndef VIGRA_ARRAY_VECTOR_HXX
37 #define VIGRA_ARRAY_VECTOR_HXX
38 
39 #include "error.hxx"
40 #include "memory.hxx"
41 #include "numerictraits.hxx"
42 #include <memory>
43 #include <algorithm>
44 #include <iosfwd>
45 
46 #ifdef VIGRA_CHECK_BOUNDS
47 #define VIGRA_ASSERT_INSIDE(diff) \
48  vigra_precondition(diff >= 0, "Index out of bounds");\
49  vigra_precondition(diff < (difference_type)size_, "Index out of bounds");
50 #else
51 #define VIGRA_ASSERT_INSIDE(diff)
52 #endif
53 
54 namespace vigra
55 {
56 
57 template <class T, class Alloc = std::allocator<T> >
59 
60 /** Provide STL conforming interface for C-arrays.
61 
62  This template implements much of the functionality of <a href="http://www.sgi.com/tech/stl/Vector.html">std::vector</a>
63  on top of a C-array. <tt>ArrayVectorView</tt> does not manage the memory
64  it refers to (i.e. it does not allocate or deallocate any memory).
65  Thus, if the underlying memory changes, all dependent <tt>ArrayVectorView</tt>
66  objects are invalidated. This is especially important when <tt>ArrayVectorView</tt>
67  is used as a base class for <tt>ArrayVector</tt>, where several functions
68  (e.g. resize(), insert()) can allocate new memory and thus invalidate the
69  dependent views. The rules what operations invalidate view objects are the
70  same as the rules concerning standard iterators.
71 
72  <b>\#include</b> <vigra/array_vector.hxx><br>
73  Namespace: vigra
74 */
75 template <class T>
77 {
79 
80 public:
81  /** default constructor
82  */
83  typedef T value_type;
84  typedef value_type & reference;
85  typedef value_type const & const_reference;
86  typedef value_type * pointer;
87  typedef value_type const * const_pointer;
88  typedef value_type * iterator;
89  typedef value_type const * const_iterator;
90  typedef std::size_t size_type;
91  typedef std::ptrdiff_t difference_type;
92  typedef std::reverse_iterator<iterator> reverse_iterator;
93  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
94 
95 public:
96  /** default constructor.
97  View contains NULL pointer.
98  */
100  : size_(0),
101  data_(0)
102  {}
103 
104  /** Construct for given array \a data of length \a size.
105  <tt>data, data+size</tt> must form a valid range.
106  */
107  ArrayVectorView( size_type size, pointer const & data)
108  : size_(size),
109  data_(data)
110  {}
111 
112  /** Copy constructor.
113  */
114  ArrayVectorView( this_type const & rhs )
115  : size_(rhs.size_),
116  data_(rhs.data_)
117  {}
118 
119  /** Copy assignment. There are 3 cases:
120 
121  <ul>
122  <li> When this <tt>ArrayVectorView</tt> does not point to valid data
123  (e.g. after default construction), it becomes a copy of \a rhs.
124  <li> When the shapes of the two arrays match, the array contents
125  (not the pointers) are copied.
126  <li> Otherwise, a <tt>PreconditionViolation</tt> exception is thrown.
127  </ul>
128  */
129  ArrayVectorView & operator=( ArrayVectorView const & rhs );
130 
131  /** Copy assignment.
132  When the shapes of the two arrays match, the array contents
133  (not the pointers) are copied. Otherwise, a <tt>PreconditionViolation</tt>
134  exception is thrown.
135  */
136  template <class U>
138  {
139  copyImpl(rhs);
140  return *this;
141  }
142 
143  /** Overwrite all array elements with the value \a initial.
144  */
145  template <class U>
146  void init(U const & initial)
147  {
148  std::fill(begin(), end(), initial);
149  }
150 
151  /** Copy array elements.
152  When the shapes of the two arrays match, the array contents
153  (not the pointers) are copied. Otherwise, a <tt>PreconditionViolation</tt>
154  exception is thrown.
155  */
156  void copy( this_type const & rhs )
157  {
158  if(data_ != rhs.data_)
159  copyImpl(rhs);
160  }
161 
162  /** Copy array elements.
163  When the shapes of the two arrays match, the array contents
164  (not the pointers) are copied. Otherwise, a <tt>PreconditionViolation</tt>
165  exception is thrown.
166  */
167  template <class U>
168  void copy( ArrayVectorView<U> const & rhs )
169  {
170  copyImpl(rhs);
171  }
172 
173  /** Swap array elements.
174  When the shapes of the two arrays match, the array contents
175  (not the pointers) are swapped. Otherwise, a <tt>PreconditionViolation</tt>
176  exception is thrown.
177  */
178  void swapData(this_type rhs)
179  {
180  if(data_ != rhs.data_)
181  swapDataImpl(rhs);
182  }
183 
184  /** Swap array elements.
185  When the shapes of the two arrays match, the array contents
186  (not the pointers) are swapped. Otherwise, a <tt>PreconditionViolation</tt>
187  exception is thrown.
188  */
189  template <class U>
191  {
192  swapDataImpl(rhs);
193  }
194 
195  /** Construct <tt>ArrayVectorView</tt> referring to a subarray.
196  \a begin and \a end must be a valid sub-range of the current array.
197  Otherwise, a <tt>PreconditionViolation</tt>
198  exception is thrown.
199  */
200  this_type subarray (size_type begin, size_type end) const
201  {
202  vigra_precondition(begin <= end && end <= size_,
203  "ArrayVectorView::subarray(): Limits out of range.");
204  return this_type(end-begin, data_ + begin);
205  }
206 
207  /** Get contained const pointer to the data.
208  */
209  inline const_pointer data() const
210  {
211  return data_;
212  }
213 
214  /** Get contained pointer to the data.
215  */
216  inline pointer data()
217  {
218  return data_;
219  }
220 
221  /** Get const iterator referring to the first array element.
222  */
223  inline const_iterator begin() const
224  {
225  return data();
226  }
227 
228  /** Get iterator referring to the first array element.
229  */
230  inline iterator begin()
231  {
232  return data();
233  }
234 
235  /** Get const iterator pointing beyond the last array element.
236  */
237  inline const_iterator end() const
238  {
239  return data() + size();
240  }
241 
242  /** Get iterator pointing beyond the last array element.
243  */
244  inline iterator end()
245  {
246  return data() + size();
247  }
248 
249  /** Get const iterator referring to the first array element.
250  */
251  inline const_iterator cbegin() const
252  {
253  return data();
254  }
255 
256  /** Get const iterator pointing beyond the last array element.
257  */
258  inline const_iterator cend() const
259  {
260  return data() + size();
261  }
262 
263  /** Get reverse iterator referring to the last array element.
264  */
265  inline reverse_iterator rbegin()
266  {
267  return (reverse_iterator(end()));
268  }
269 
270  /** Get const reverse iterator referring to the last array element.
271  */
272  inline const_reverse_iterator rbegin() const
273  {
274  return (const_reverse_iterator(end()));
275  }
276 
277  /** Get reverse iterator pointing before the first array element.
278  */
279  inline reverse_iterator rend()
280  {
281  return (reverse_iterator(begin()));
282  }
283 
284  /** Get const reverse iterator pointing before the first array element.
285  */
286  inline const_reverse_iterator rend() const
287  {
288  return (const_reverse_iterator(begin()));
289  }
290 
291  /** Get const reverse iterator referring to the last array element.
292  */
293  inline const_reverse_iterator crbegin() const
294  {
295  return (const_reverse_iterator(end()));
296  }
297 
298  /** Get const reverse iterator pointing before the first array element.
299  */
300  inline const_reverse_iterator crend() const
301  {
302  return (const_reverse_iterator(begin()));
303  }
304 
305  /** Access first array element.
306  */
307  reference front()
308  {
309  return *data_;
310  }
311 
312  /** Read first array element.
313  */
314  const_reference front() const
315  {
316  return *data_;
317  }
318 
319  /** Access last array element.
320  */
321  reference back()
322  {
323  return data_[size_-1];
324  }
325 
326  /** Read last array element.
327  */
328  const_reference back() const
329  {
330  return data_[size_-1];
331  }
332 
333  /** Access array element \a i.
334  */
335  reference operator[]( difference_type i )
336  {
337  VIGRA_ASSERT_INSIDE(i);
338  return data()[i];
339  }
340 
341  /** Read array element \a i.
342  */
343  const_reference operator[]( difference_type i ) const
344  {
345  VIGRA_ASSERT_INSIDE(i);
346  return data()[i];
347  }
348 
349  /** Equivalent to <tt>size() == 0</tt>.
350  */
351  bool empty() const
352  {
353  return size_ == 0;
354  }
355 
356  /** Number of elements in the array.
357  */
358  size_type size() const
359  {
360  return size_;
361  }
362 
363  /** Check for element-wise equality of two array.
364  Also returns <tt>false</tt> if the two arrays have different sizes.
365  */
366  template <class U>
367  bool operator==(ArrayVectorView<U> const & rhs) const;
368 
369  /** check whether two arrays are not elementwise equal.
370  Also returns <tt>true</tt> if the two arrays have different sizes.
371  */
372  template <class U>
373  bool operator!=(ArrayVectorView<U> const & rhs) const
374  {
375  return !operator==(rhs);
376  }
377 
378  /** check whether the given point is in the array range.
379  */
380  bool isInside (difference_type const & p) const
381  {
382  return p >= 0 && p < size_;
383  }
384 
385  protected:
386 
387  template <class U>
388  void copyImpl(const ArrayVectorView <U>& rhs);
389 
390  void copyImpl(const ArrayVectorView & rhs);
391 
392  template <class U>
393  void swapDataImpl(const ArrayVectorView <U>& rhs);
394 
395  size_type size_;
396  pointer data_;
397 };
398 
399 template <class T>
400 ArrayVectorView<T> & ArrayVectorView<T>::operator=( ArrayVectorView<T> const & rhs )
401 {
402  if(data_ == 0)
403  {
404  size_ = rhs.size_;
405  data_ = rhs.data_;
406  }
407  else if(data_ != rhs.data_)
408  copyImpl(rhs);
409  return *this;
410 }
411 
412 template <class T>
413 template <class U>
415 {
416  if(size() != rhs.size())
417  return false;
418  for(size_type k=0; k<size(); ++k)
419  if(data_[k] != rhs[k])
420  return false;
421  return true;
422 }
423 
424 template <class T>
425 void
427 {
428  vigra_precondition (size() == rhs.size(),
429  "ArrayVectorView::copy(): shape mismatch.");
430  if(size() == 0) // needed because MSVC debug assertions in std::copy() may fire
431  return; // "invalid address: data_ == NULL" even when nothing is to be copied
432  // use copy() or copy_backward() according to possible overlap of this and rhs
433  if(data_ <= rhs.data())
434  {
435  std::copy(rhs.begin(), rhs.end(), begin());
436  }
437  else
438  {
439  std::copy_backward(rhs.begin(), rhs.end(), end());
440  }
441 }
442 
443 template <class T>
444 template <class U>
445 void
446 ArrayVectorView <T>::copyImpl(const ArrayVectorView <U>& rhs)
447 {
448  vigra_precondition (size() == rhs.size(),
449  "ArrayVectorView::copy(): shape mismatch.");
450  std::copy(rhs.begin(), rhs.end(), begin());
451 }
452 
453 template <class T>
454 template <class U>
455 void
456 ArrayVectorView <T>::swapDataImpl(const ArrayVectorView <U>& rhs)
457 {
458  vigra_precondition (size () == rhs.size() (),
459  "ArrayVectorView::swapData(): size mismatch.");
460 
461  // check for overlap
462  if(data_ + size_ <= rhs.data_ || rhs.data_ + size_ <= data_)
463  {
464  for(size_type k=0; k<size_; ++k)
465  std::swap(data_[k], rhs.data_[k]);
466  }
467  else
468  {
469  ArrayVector<T> t(*this);
470  copyImpl(rhs);
471  rhs.copyImpl(*this);
472  }
473 }
474 
475 
476 /** Replacement for <tt>std::vector</tt>.
477 
478  This template implements the same functionality as <tt>a href="http://www.sgi.com/tech/stl/Vector.html">std::vector</a></tt> (see there for detailed documentation).
479  However, it gives two useful guarantees, that <tt>std::vector</tt> fails
480  to provide:
481 
482  <ul>
483  <li>The memory is always allocated as one contiguous piece.</li>
484  <li>The iterator is always a <TT>T *</TT> </li>
485  </ul>
486 
487  This means that memory managed by <tt>ArrayVector</tt> can be passed
488  to algorithms that expect raw memory. This is especially important
489  when legacy or C code has to be called, but it is also useful for certain
490  optimizations.
491 
492  Moreover, <tt>ArrayVector</tt> is derived from <tt>ArrayVectorView</tt> so that one
493  can create views of the array (in particular, subarrays). This implies another
494  important difference to <tt>std::vector</tt>: the indexing operator
495  (<tt>ArrayVector::operator[]</tt>) takes <tt>signed</tt> indices. In this way,
496  an <tt>ArrayVectorView</tt> can be used with negative indices:
497 
498  \code
499  ArrayVector<int> data(100);
500  ArrayVectorView<int> view = data.subarray(50, 100);
501 
502  view[-50] = 1; // valid access
503  \endcode
504 
505  Refer to the documentation of <tt>std::vector</tt> for a detailed
506  description of <tt>ArrayVector</tt> functionality.
507 
508  <b>\#include</b> <vigra/array_vector.hxx><br>
509  Namespace: vigra
510 */
511 template <class T, class Alloc /* = std::allocator<T> */ >
512 class ArrayVector
513 : public ArrayVectorView<T>
514 {
515  typedef ArrayVector<T, Alloc> this_type;
516  enum { minimumCapacity = 2, resizeFactor = 2 };
517 
518 public:
519  typedef ArrayVectorView<T> view_type;
520  typedef typename view_type::value_type value_type;
521  typedef typename view_type::reference reference;
522  typedef typename view_type::const_reference const_reference;
523  typedef typename view_type::pointer pointer;
524  typedef typename view_type::const_pointer const_pointer;
525  typedef typename view_type::iterator iterator;
526  typedef typename view_type::const_iterator const_iterator;
527  typedef typename view_type::size_type size_type;
528  typedef typename view_type::difference_type difference_type;
529  typedef typename view_type::reverse_iterator reverse_iterator;
530  typedef typename view_type::const_reverse_iterator const_reverse_iterator;
531  typedef Alloc allocator_type;
532 
533 public:
534  ArrayVector()
535  : view_type(),
536  capacity_(minimumCapacity),
537  alloc_(Alloc())
538  {
539  this->data_ = reserve_raw(capacity_);
540  }
541 
542  explicit ArrayVector(Alloc const & alloc)
543  : view_type(),
544  capacity_(minimumCapacity),
545  alloc_(alloc)
546  {
547  this->data_ = reserve_raw(capacity_);
548  }
549 
550  explicit ArrayVector( size_type size, Alloc const & alloc = Alloc())
551  : view_type(),
552  alloc_(alloc)
553  {
554  initImpl(size, value_type(), VigraTrueType());
555  }
556 
557  ArrayVector( size_type size, value_type const & initial, Alloc const & alloc = Alloc())
558  : view_type(),
559  alloc_(alloc)
560  {
561  initImpl(size, initial, VigraTrueType());
562  }
563 
564 
565  ArrayVector( this_type const & rhs )
566  : view_type(),
567  alloc_(rhs.alloc_)
568  {
569  initImpl(rhs.begin(), rhs.end(), VigraFalseType());
570  }
571 
572  template <class U>
573  explicit ArrayVector( ArrayVectorView<U> const & rhs, Alloc const & alloc = Alloc() )
574  : view_type(),
575  alloc_(alloc)
576  {
577  initImpl(rhs.begin(), rhs.end(), VigraFalseType());
578  }
579 
580  template <class InputIterator>
581  ArrayVector(InputIterator i, InputIterator end)
582  {
583  initImpl(i, end, typename NumericTraits<InputIterator>::isIntegral());
584  }
585 
586  template <class InputIterator>
587  ArrayVector(InputIterator i, InputIterator end, Alloc const & alloc)
588  : alloc_(alloc)
589  {
590  initImpl(i, end, typename NumericTraits<InputIterator>::isIntegral());
591  }
592 
593  this_type & operator=( this_type const & rhs )
594  {
595  if(this == &rhs)
596  return *this;
597  if(this->size_ == rhs.size_)
598  this->copyImpl(rhs);
599  else
600  {
601  ArrayVector t(rhs);
602  this->swap(t);
603  }
604  return *this;
605  }
606 
607  template <class U>
608  this_type & operator=( ArrayVectorView<U> const & rhs);
609 
610  ~ArrayVector()
611  {
612  deallocate(this->data_, this->size_);
613  }
614 
615  void pop_back();
616 
617  void push_back( value_type const & t );
618 
619  iterator insert(iterator p, value_type const & v);
620 
621  iterator insert(iterator p, size_type n, value_type const & v);
622 
623  template <class InputIterator>
624  iterator insert(iterator p, InputIterator i, InputIterator iend);
625 
626  iterator erase(iterator p);
627 
628  iterator erase(iterator p, iterator q);
629 
630  void clear();
631 
632  pointer reserveImpl( bool dealloc, size_type new_capacity );
633 
634  pointer reserveImpl( bool dealloc);
635 
636  void reserve()
637  {
638  reserveImpl(true);
639  }
640 
641  void reserve( size_type new_capacity )
642  {
643  reserveImpl(true, new_capacity);
644  }
645 
646  void resize( size_type new_size, value_type const & initial );
647 
648  void resize( size_type new_size )
649  {
650  resize(new_size, value_type());
651  }
652 
653  size_type capacity() const
654  {
655  return capacity_;
656  }
657 
658  void swap(this_type & rhs);
659 
660  private:
661 
662  void deallocate(pointer data, size_type size);
663 
664  pointer reserve_raw(size_type capacity);
665 
666  void initImpl( size_type size, value_type const & initial, VigraTrueType /*isIntegral*/);
667 
668  template <class Iter>
669  void initImpl( Iter i, Iter end, VigraFalseType /*isIntegral*/);
670 
671  template <class Iter>
672  void initImpl( Iter i, Iter end, Error_NumericTraits_not_specialized_for_this_case)
673  {
674  initImpl(i, end, VigraFalseType());
675  }
676 
677  size_type capacity_;
678  Alloc alloc_;
679 };
680 
681 template <class T, class Alloc>
682 template <class U>
683 ArrayVector<T, Alloc> & ArrayVector<T, Alloc>::operator=( ArrayVectorView<U> const & rhs )
684 {
685  if(this->size_ == rhs.size())
686  this->copyImpl(rhs);
687  else
688  {
689  ArrayVector t(rhs);
690  this->swap(t);
691  }
692  return *this;
693 }
694 
695 template <class T, class Alloc>
696 inline void ArrayVector<T, Alloc>::pop_back()
697 {
698  --this->size_;
699  alloc_.destroy(this->data_ + this->size_);
700 }
701 
702 template <class T, class Alloc>
703 inline void ArrayVector<T, Alloc>::push_back( value_type const & t )
704 {
705  pointer old_data = reserveImpl(false);
706  alloc_.construct(this->data_ + this->size_, t);
707  // deallocate old data _after_ construction of new element, so that
708  // 't' can refer to the old data as in 'push_back(front())'
709  deallocate(old_data, this->size_);
710  ++this->size_;
711 }
712 
713 template <class T, class Alloc>
714 inline void ArrayVector<T, Alloc>::clear()
715 {
716  detail::destroy_n(this->data_, this->size_);
717  this->size_ = 0;
718 }
719 
720 template <class T, class Alloc>
721 typename ArrayVector<T, Alloc>::iterator
722 ArrayVector<T, Alloc>::insert(iterator p, value_type const & v)
723 {
724  difference_type pos = p - this->begin();
725  if(p == this->end())
726  {
727  push_back(v);
728  p = this->begin() + pos;
729  }
730  else
731  {
732  T lastElement = this->back();
733  push_back(lastElement);
734  p = this->begin() + pos;
735  std::copy_backward(p, this->end() - 2, this->end() - 1);
736  *p = v;
737  }
738  return p;
739 }
740 
741 template <class T, class Alloc>
742 typename ArrayVector<T, Alloc>::iterator
743 ArrayVector<T, Alloc>::insert(iterator p, size_type n, value_type const & v)
744 {
745  difference_type pos = p - this->begin();
746  size_type new_size = this->size() + n;
747  if(new_size > capacity_)
748  {
749  size_type new_capacity = std::max(new_size, resizeFactor*capacity_);
750  pointer new_data = reserve_raw(new_capacity);
751  try
752  {
753  std::uninitialized_copy(this->begin(), p, new_data);
754  std::uninitialized_fill(new_data + pos, new_data + pos + n, v);
755  std::uninitialized_copy(p, this->end(), new_data + pos + n);
756  }
757  catch(...)
758  {
759  alloc_.deallocate(new_data, new_capacity);
760  throw;
761  }
762  deallocate(this->data_, this->size_);
763  capacity_ = new_capacity;
764  this->data_ = new_data;
765  }
766  else if(pos + n > this->size_)
767  {
768  size_type diff = pos + n - this->size_;
769  std::uninitialized_copy(p, this->end(), this->end() + diff);
770  std::uninitialized_fill(this->end(), this->end() + diff, v);
771  std::fill(p, this->end(), v);
772  }
773  else
774  {
775  size_type diff = this->size_ - (pos + n);
776  std::uninitialized_copy(this->end() - n, this->end(), this->end());
777  std::copy_backward(p, p + diff, this->end());
778  std::fill(p, p + n, v);
779  }
780  this->size_ = new_size;
781  return this->begin() + pos;
782 }
783 
784 template <class T, class Alloc>
785 template <class InputIterator>
786 typename ArrayVector<T, Alloc>::iterator
787 ArrayVector<T, Alloc>::insert(iterator p, InputIterator i, InputIterator iend)
788 {
789  size_type n = std::distance(i, iend);
790  size_type pos = p - this->begin();
791  size_type new_size = this->size() + n;
792  if(new_size > capacity_)
793  {
794  size_type new_capacity = std::max(new_size, resizeFactor*capacity_);
795  pointer new_data = reserve_raw(new_capacity);
796  try
797  {
798  std::uninitialized_copy(this->begin(), p, new_data);
799  std::uninitialized_copy(i, iend, new_data + pos);
800  std::uninitialized_copy(p, this->end(), new_data + pos + n);
801  }
802  catch(...)
803  {
804  alloc_.deallocate(new_data, new_capacity);
805  throw;
806  }
807  deallocate(this->data_, this->size_);
808  capacity_ = new_capacity;
809  this->data_ = new_data;
810  }
811  else if(pos + n > this->size_)
812  {
813  size_type diff = pos + n - this->size_;
814  std::uninitialized_copy(p, this->end(), this->end() + diff);
815  InputIterator split = i;
816  std::advance(split, n - diff);
817  std::uninitialized_copy(split, iend, this->end());
818  std::copy(i, split, p);
819  }
820  else
821  {
822  size_type diff = this->size_ - (pos + n);
823  std::uninitialized_copy(this->end() - n, this->end(), this->end());
824  std::copy_backward(p, p + diff, this->end());
825  std::copy(i, iend, p);
826  }
827  this->size_ = new_size;
828  return this->begin() + pos;
829 }
830 
831 template <class T, class Alloc>
832 typename ArrayVector<T, Alloc>::iterator
833 ArrayVector<T, Alloc>::erase(iterator p)
834 {
835  std::copy(p+1, this->end(), p);
836  pop_back();
837  return p;
838 }
839 
840 template <class T, class Alloc>
841 typename ArrayVector<T, Alloc>::iterator
842 ArrayVector<T, Alloc>::erase(iterator p, iterator q)
843 {
844  std::copy(q, this->end(), p);
845  difference_type eraseCount = q - p;
846  detail::destroy_n(this->end() - eraseCount, eraseCount);
847  this->size_ -= eraseCount;
848  return p;
849 }
850 
851 template <class T, class Alloc>
852 typename ArrayVector<T, Alloc>::pointer
853 ArrayVector<T, Alloc>::reserveImpl( bool dealloc, size_type new_capacity)
854 {
855  if(new_capacity <= capacity_)
856  return 0;
857  pointer new_data = reserve_raw(new_capacity),
858  old_data = this->data_;
859  if(this->size_ > 0)
860  std::uninitialized_copy(old_data, old_data+this->size_, new_data);
861  this->data_ = new_data;
862  capacity_ = new_capacity;
863  if(!dealloc)
864  return old_data;
865  deallocate(old_data, this->size_);
866  return 0;
867 }
868 
869 template <class T, class Alloc>
870 inline typename ArrayVector<T, Alloc>::pointer
871 ArrayVector<T, Alloc>::reserveImpl(bool dealloc)
872 {
873  if(capacity_ == 0)
874  return reserveImpl(dealloc, minimumCapacity);
875  else if(this->size_ == capacity_)
876  return reserveImpl(dealloc, resizeFactor*capacity_);
877  else
878  return 0;
879 }
880 
881 template <class T, class Alloc>
882 inline void
883 ArrayVector<T, Alloc>::resize( size_type new_size, value_type const & initial)
884 {
885  if(new_size < this->size_)
886  erase(this->begin() + new_size, this->end());
887  else if(this->size_ < new_size)
888  {
889  insert(this->end(), new_size - this->size(), initial);
890  }
891 }
892 
893 template <class T, class Alloc>
894 inline void
895 ArrayVector<T, Alloc>::initImpl( size_type size, value_type const & initial, VigraTrueType /*isIntegral*/)
896 {
897  this->size_ = size;
898  capacity_ = size;
899  this->data_ = reserve_raw(capacity_);
900  if(this->size_ > 0)
901  std::uninitialized_fill(this->data_, this->data_+this->size_, initial);
902 }
903 
904 template <class T, class Alloc>
905 template <class Iter>
906 inline void
907 ArrayVector<T, Alloc>::initImpl( Iter i, Iter end, VigraFalseType /*isIntegral*/)
908 {
909  this->size_ = std::distance(i, end);
910  capacity_ = this->size_;
911  this->data_ = reserve_raw(capacity_);
912  if(this->size_ > 0)
913  detail::uninitializedCopy(i, end, this->data_);
914 }
915 
916 template <class T, class Alloc>
917 inline void
918 ArrayVector<T, Alloc>::swap(this_type & rhs)
919 {
920  std::swap(this->size_, rhs.size_);
921  std::swap(capacity_, rhs.capacity_);
922  std::swap(this->data_, rhs.data_);
923 }
924 
925 template <class T, class Alloc>
926 inline void
927 ArrayVector<T, Alloc>::deallocate(pointer data, size_type size)
928 {
929  if(data)
930  {
931  detail::destroy_n(data, size);
932  alloc_.deallocate(data, size);
933  }
934 }
935 
936 template <class T, class Alloc>
937 inline typename ArrayVector<T, Alloc>::pointer
938 ArrayVector<T, Alloc>::reserve_raw(size_type capacity)
939 {
940  pointer data = 0;
941  if(capacity)
942  {
943  data = alloc_.allocate(capacity);
944  }
945  return data;
946 }
947 
948 } // namespace vigra
949 
950 namespace std {
951 
952 template <class T>
953 ostream & operator<<(ostream & s, vigra::ArrayVectorView<T> const & a)
954 {
955  for(std::size_t k=0; k<a.size()-1; ++k)
956  s << a[k] << ", ";
957  if(a.size())
958  s << a.back();
959  return s;
960 }
961 
962 } // namespace std
963 
964 #undef VIGRA_ASSERT_INSIDE
965 #endif /* VIGRA_ARRAY_VECTOR_HXX */

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.10.0 (Thu Jan 8 2015)