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

array_vector.hxx
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((unsigned int)diff < 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> >
58 class ArrayVector;
59 
60 /** Provide STL conforming interface for C-arrays.
61 
62  This template implements much of the functionality of <tt><a href="http://www.sgi.com/tech/stl/Vector.html">std::vector</a></tt>
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 reverse iterator referring to the last array element.
250  */
251  inline reverse_iterator rbegin()
252  {
253  return (reverse_iterator(end()));
254  }
255 
256  /** Get const reverse iterator referring to the last array element.
257  */
258  inline const_reverse_iterator rbegin() const
259  {
260  return (const_reverse_iterator(end()));
261  }
262 
263  /** Get reverse iterator pointing before the first array element.
264  */
265  inline reverse_iterator rend()
266  {
267  return (reverse_iterator(begin()));
268  }
269 
270  /** Get const reverse iterator pointing before the first array element.
271  */
272  inline const_reverse_iterator rend() const
273  {
274  return (const_reverse_iterator(begin()));
275  }
276 
277  /** Access first array element.
278  */
279  reference front()
280  {
281  return *data_;
282  }
283 
284  /** Read first array element.
285  */
286  const_reference front() const
287  {
288  return *data_;
289  }
290 
291  /** Access last array element.
292  */
293  reference back()
294  {
295  return data_[size_-1];
296  }
297 
298  /** Read last array element.
299  */
300  const_reference back() const
301  {
302  return data_[size_-1];
303  }
304 
305  /** Access array element \a i.
306  */
307  reference operator[]( difference_type i )
308  {
309  VIGRA_ASSERT_INSIDE(i);
310  return data()[i];
311  }
312 
313  /** Read array element \a i.
314  */
315  const_reference operator[]( difference_type i ) const
316  {
317  VIGRA_ASSERT_INSIDE(i);
318  return data()[i];
319  }
320 
321  /** Equivalent to <tt>size() == 0</tt>.
322  */
323  bool empty() const
324  {
325  return size_ == 0;
326  }
327 
328  /** Number of elements in the array.
329  */
330  size_type size() const
331  {
332  return size_;
333  }
334 
335  /** Check for element-wise equality of two array.
336  Also returns <tt>false</tt> if the two arrays have different sizes.
337  */
338  template <class U>
339  bool operator==(ArrayVectorView<U> const & rhs) const;
340 
341  /** check whether two arrays are not elementwise equal.
342  Also returns <tt>true</tt> if the two arrays have different sizes.
343  */
344  template <class U>
345  bool operator!=(ArrayVectorView<U> const & rhs) const
346  {
347  return !operator==(rhs);
348  }
349 
350  /** check whether the given point is in the array range.
351  */
352  bool isInside (difference_type const & p) const
353  {
354  return p >= 0 && p < size_;
355  }
356 
357  protected:
358 
359  template <class U>
360  void copyImpl(const ArrayVectorView <U>& rhs);
361 
362  void copyImpl(const ArrayVectorView & rhs);
363 
364  template <class U>
365  void swapDataImpl(const ArrayVectorView <U>& rhs);
366 
367  size_type size_;
368  pointer data_;
369 };
370 
371 template <class T>
372 ArrayVectorView<T> & ArrayVectorView<T>::operator=( ArrayVectorView<T> const & rhs )
373 {
374  if(data_ == 0)
375  {
376  size_ = rhs.size_;
377  data_ = rhs.data_;
378  }
379  else if(data_ != rhs.data_)
380  copyImpl(rhs);
381  return *this;
382 }
383 
384 template <class T>
385 template <class U>
387 {
388  if(size() != rhs.size())
389  return false;
390  for(unsigned int k=0; k<size(); ++k)
391  if(data_[k] != rhs[k])
392  return false;
393  return true;
394 }
395 
396 template <class T>
397 void
399 {
400  vigra_precondition (size() == rhs.size(),
401  "ArrayVectorView::copy(): shape mismatch.");
402  // use copy() or copy_backward() according to possible overlap of this and rhs
403  if(data_ <= rhs.data())
404  {
405  std::copy(rhs.begin(), rhs.end(), begin());
406  }
407  else
408  {
409  std::copy_backward(rhs.begin(), rhs.end(), end());
410  }
411 }
412 
413 template <class T>
414 template <class U>
415 void
416 ArrayVectorView <T>::copyImpl(const ArrayVectorView <U>& rhs)
417 {
418  vigra_precondition (size() == rhs.size(),
419  "ArrayVectorView::copy(): shape mismatch.");
420  std::copy(rhs.begin(), rhs.end(), begin());
421 }
422 
423 template <class T>
424 template <class U>
425 void
426 ArrayVectorView <T>::swapDataImpl(const ArrayVectorView <U>& rhs)
427 {
428  vigra_precondition (size () == rhs.size() (),
429  "ArrayVectorView::swapData(): size mismatch.");
430 
431  // check for overlap
432  if(data_ + size_ <= rhs.data_ || rhs.data_ + size_ <= data_)
433  {
434  for(unsigned int k=0; k<size_; ++k)
435  std::swap(data_[k], rhs.data_[k]);
436  }
437  else
438  {
439  ArrayVector<T> t(*this);
440  copyImpl(rhs);
441  rhs.copyImpl(*this);
442  }
443 }
444 
445 
446 /** Replacement for <tt>std::vector</tt>.
447 
448  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).
449  However, it gives two useful guarantees, that <tt>std::vector</tt> fails
450  to provide:
451 
452  <ul>
453  <li>The memory is always allocated as one contiguous piece.</li>
454  <li>The iterator is always a <TT>T *</TT> </li>
455  </ul>
456 
457  This means that memory managed by <tt>ArrayVector</tt> can be passed
458  to algorithms that expect raw memory. This is especially important
459  when legacy or C code has to be called, but it is also useful for certain
460  optimizations.
461 
462  Moreover, <tt>ArrayVector</tt> is derived from <tt>ArrayVectorView</tt> so that one
463  can create views of the array (in particular, subarrays). This implies another
464  important difference to <tt>std::vector</tt>: the indexing operator
465  (<tt>ArrayVector::operator[]</tt>) takes <tt>signed</tt> indices. In this way,
466  an <tt>ArrayVectorView</tt> can be used with negative indices:
467 
468  \code
469  ArrayVector<int> data(100);
470  ArrayVectorView<int> view = data.subarray(50, 100);
471 
472  view[-50] = 1; // valid access
473  \endcode
474 
475  Refer to the documentation of <tt>std::vector</tt> for a detailed
476  description of <tt>ArrayVector</tt> functionality.
477 
478  <b>\#include</b> <vigra/array_vector.hxx><br>
479  Namespace: vigra
480 */
481 template <class T, class Alloc /* = std::allocator<T> */ >
483 : public ArrayVectorView<T>
484 {
486  enum { minimumCapacity = 2, resizeFactor = 2 };
487 
488 public:
490  typedef typename view_type::value_type value_type;
491  typedef typename view_type::reference reference;
492  typedef typename view_type::const_reference const_reference;
493  typedef typename view_type::pointer pointer;
494  typedef typename view_type::const_pointer const_pointer;
495  typedef typename view_type::iterator iterator;
496  typedef typename view_type::const_iterator const_iterator;
497  typedef typename view_type::size_type size_type;
498  typedef typename view_type::difference_type difference_type;
499  typedef typename view_type::reverse_iterator reverse_iterator;
500  typedef typename view_type::const_reverse_iterator const_reverse_iterator;
501  typedef Alloc allocator_type;
502 
503 public:
504  ArrayVector()
505  : view_type(),
506  capacity_(minimumCapacity),
507  alloc_(Alloc())
508  {
509  this->data_ = reserve_raw(capacity_);
510  }
511 
512  explicit ArrayVector(Alloc const & alloc)
513  : view_type(),
514  capacity_(minimumCapacity),
515  alloc_(alloc)
516  {
517  this->data_ = reserve_raw(capacity_);
518  }
519 
520  explicit ArrayVector( size_type size, Alloc const & alloc = Alloc())
521  : view_type(),
522  alloc_(alloc)
523  {
524  initImpl(size, value_type(), VigraTrueType());
525  }
526 
527  ArrayVector( size_type size, value_type const & initial, Alloc const & alloc = Alloc())
528  : view_type(),
529  alloc_(alloc)
530  {
531  initImpl(size, initial, VigraTrueType());
532  }
533 
534 
535  ArrayVector( this_type const & rhs )
536  : view_type(),
537  alloc_(rhs.alloc_)
538  {
539  initImpl(rhs.begin(), rhs.end(), VigraFalseType());
540  }
541 
542  template <class U>
543  explicit ArrayVector( ArrayVectorView<U> const & rhs, Alloc const & alloc = Alloc() )
544  : view_type(),
545  alloc_(alloc)
546  {
547  initImpl(rhs.begin(), rhs.end(), VigraFalseType());
548  }
549 
550  template <class InputIterator>
551  ArrayVector(InputIterator i, InputIterator end)
552  {
553  initImpl(i, end, typename NumericTraits<InputIterator>::isIntegral());
554  }
555 
556  template <class InputIterator>
557  ArrayVector(InputIterator i, InputIterator end, Alloc const & alloc)
558  : alloc_(alloc)
559  {
560  initImpl(i, end, typename NumericTraits<InputIterator>::isIntegral());
561  }
562 
563  this_type & operator=( this_type const & rhs )
564  {
565  if(this == &rhs)
566  return *this;
567  if(this->size_ == rhs.size_)
568  this->copyImpl(rhs);
569  else
570  {
571  ArrayVector t(rhs);
572  this->swap(t);
573  }
574  return *this;
575  }
576 
577  template <class U>
578  this_type & operator=( ArrayVectorView<U> const & rhs);
579 
580  ~ArrayVector()
581  {
582  deallocate(this->data_, this->size_);
583  }
584 
585  void pop_back();
586 
587  void push_back( value_type const & t );
588 
589  iterator insert(iterator p, value_type const & v);
590 
591  iterator insert(iterator p, size_type n, value_type const & v);
592 
593  template <class InputIterator>
594  iterator insert(iterator p, InputIterator i, InputIterator iend);
595 
596  iterator erase(iterator p);
597 
598  iterator erase(iterator p, iterator q);
599 
600  void clear();
601 
602  void reserve( size_type new_capacity );
603 
604  void reserve();
605 
606  void resize( size_type new_size, value_type const & initial );
607 
608  void resize( size_type new_size )
609  {
610  resize(new_size, value_type());
611  }
612 
613  size_type capacity() const
614  {
615  return capacity_;
616  }
617 
618  void swap(this_type & rhs);
619 
620  private:
621 
622  void deallocate(pointer data, size_type size);
623 
624  pointer reserve_raw(size_type capacity);
625 
626  void initImpl( size_type size, value_type const & initial, VigraTrueType /*isIntegral*/);
627 
628  template <class Iter>
629  void initImpl( Iter i, Iter end, VigraFalseType /*isIntegral*/);
630 
631  template <class Iter>
632  void initImpl( Iter i, Iter end, Error_NumericTraits_not_specialized_for_this_case)
633  {
634  initImpl(i, end, VigraFalseType());
635  }
636 
637  size_type capacity_;
638  Alloc alloc_;
639 };
640 
641 template <class T, class Alloc>
642 template <class U>
644 {
645  if(this->size_ == rhs.size())
646  this->copyImpl(rhs);
647  else
648  {
649  ArrayVector t(rhs);
650  this->swap(t);
651  }
652  return *this;
653 }
654 
655 template <class T, class Alloc>
657 {
658  --this->size_;
659  alloc_.destroy(this->data_ + this->size_);
660 }
661 
662 template <class T, class Alloc>
663 inline void ArrayVector<T, Alloc>::push_back( value_type const & t )
664 {
665  reserve();
666  alloc_.construct(this->data_ + this->size_, t);
667  ++this->size_;
668 }
669 
670 template <class T, class Alloc>
671 inline void ArrayVector<T, Alloc>::clear()
672 {
673  detail::destroy_n(this->data_, (int)this->size_);
674  this->size_ = 0;
675 }
676 
677 template <class T, class Alloc>
678 typename ArrayVector<T, Alloc>::iterator
679 ArrayVector<T, Alloc>::insert(iterator p, value_type const & v)
680 {
681  difference_type pos = p - this->begin();
682  if(p == this->end())
683  {
684  push_back(v);
685  p = this->begin() + pos;
686  }
687  else
688  {
689  push_back(this->back());
690  p = this->begin() + pos;
691  std::copy_backward(p, this->end() - 2, this->end() - 1);
692  *p = v;
693  }
694  return p;
695 }
696 
697 template <class T, class Alloc>
698 typename ArrayVector<T, Alloc>::iterator
699 ArrayVector<T, Alloc>::insert(iterator p, size_type n, value_type const & v)
700 {
701  difference_type pos = p - this->begin();
702  size_type new_size = this->size() + n;
703  if(new_size > capacity_)
704  {
705  size_type new_capacity = std::max(new_size, resizeFactor*capacity_);
706  pointer new_data = reserve_raw(new_capacity);
707  try
708  {
709  std::uninitialized_copy(this->begin(), p, new_data);
710  std::uninitialized_fill(new_data + pos, new_data + pos + n, v);
711  std::uninitialized_copy(p, this->end(), new_data + pos + n);
712  }
713  catch(...)
714  {
715  alloc_.deallocate(new_data, new_capacity);
716  throw;
717  }
718  deallocate(this->data_, this->size_);
719  capacity_ = new_capacity;
720  this->data_ = new_data;
721  }
722  else if(pos + n > this->size_)
723  {
724  size_type diff = pos + n - this->size_;
725  std::uninitialized_copy(p, this->end(), this->end() + diff);
726  std::uninitialized_fill(this->end(), this->end() + diff, v);
727  std::fill(p, this->end(), v);
728  }
729  else
730  {
731  size_type diff = this->size_ - (pos + n);
732  std::uninitialized_copy(this->end() - n, this->end(), this->end());
733  std::copy_backward(p, p + diff, this->end());
734  std::fill(p, p + n, v);
735  }
736  this->size_ = new_size;
737  return this->begin() + pos;
738 }
739 
740 template <class T, class Alloc>
741 template <class InputIterator>
742 typename ArrayVector<T, Alloc>::iterator
743 ArrayVector<T, Alloc>::insert(iterator p, InputIterator i, InputIterator iend)
744 {
745  size_type n = std::distance(i, iend);
746  size_type pos = p - this->begin();
747  size_type new_size = this->size() + n;
748  if(new_size > capacity_)
749  {
750  size_type new_capacity = std::max(new_size, resizeFactor*capacity_);
751  pointer new_data = reserve_raw(new_capacity);
752  try
753  {
754  std::uninitialized_copy(this->begin(), p, new_data);
755  std::uninitialized_copy(i, iend, new_data + pos);
756  std::uninitialized_copy(p, this->end(), new_data + pos + n);
757  }
758  catch(...)
759  {
760  alloc_.deallocate(new_data, new_capacity);
761  throw;
762  }
763  deallocate(this->data_, this->size_);
764  capacity_ = new_capacity;
765  this->data_ = new_data;
766  }
767  else if(pos + n > this->size_)
768  {
769  size_type diff = pos + n - this->size_;
770  std::uninitialized_copy(p, this->end(), this->end() + diff);
771  InputIterator split = i;
772  std::advance(split, n - diff);
773  std::uninitialized_copy(split, iend, this->end());
774  std::copy(i, split, p);
775  }
776  else
777  {
778  size_type diff = this->size_ - (pos + n);
779  std::uninitialized_copy(this->end() - n, this->end(), this->end());
780  std::copy_backward(p, p + diff, this->end());
781  std::copy(i, iend, p);
782  }
783  this->size_ = new_size;
784  return this->begin() + pos;
785 }
786 
787 template <class T, class Alloc>
788 typename ArrayVector<T, Alloc>::iterator
789 ArrayVector<T, Alloc>::erase(iterator p)
790 {
791  std::copy(p+1, this->end(), p);
792  pop_back();
793  return p;
794 }
795 
796 template <class T, class Alloc>
797 typename ArrayVector<T, Alloc>::iterator
798 ArrayVector<T, Alloc>::erase(iterator p, iterator q)
799 {
800  std::copy(q, this->end(), p);
801  difference_type eraseCount = q - p;
802  detail::destroy_n(this->end() - eraseCount, eraseCount);
803  this->size_ -= eraseCount;
804  return p;
805 }
806 
807 template <class T, class Alloc>
808 inline void
809 ArrayVector<T, Alloc>::reserve( size_type new_capacity )
810 {
811  if(new_capacity <= capacity_)
812  return;
813  pointer new_data = reserve_raw(new_capacity);
814  if(this->size_ > 0)
815  std::uninitialized_copy(this->data_, this->data_+this->size_, new_data);
816  deallocate(this->data_, this->size_);
817  this->data_ = new_data;
818  capacity_ = new_capacity;
819 }
820 
821 template <class T, class Alloc>
822 inline void
823 ArrayVector<T, Alloc>::reserve()
824 {
825  if(capacity_ == 0)
826  reserve(minimumCapacity);
827  else if(this->size_ == capacity_)
828  reserve(resizeFactor*capacity_);
829 }
830 
831 template <class T, class Alloc>
832 inline void
833 ArrayVector<T, Alloc>::resize( size_type new_size, value_type const & initial)
834 {
835  if(new_size < this->size_)
836  erase(this->begin() + new_size, this->end());
837  else if(this->size_ < new_size)
838  {
839  insert(this->end(), new_size - this->size(), initial);
840  }
841 }
842 
843 template <class T, class Alloc>
844 inline void
845 ArrayVector<T, Alloc>::initImpl( size_type size, value_type const & initial, VigraTrueType /*isIntegral*/)
846 {
847  this->size_ = size;
848  capacity_ = size;
849  this->data_ = reserve_raw(capacity_);
850  if(this->size_ > 0)
851  std::uninitialized_fill(this->data_, this->data_+this->size_, initial);
852 }
853 
854 template <class T, class Alloc>
855 template <class Iter>
856 inline void
857 ArrayVector<T, Alloc>::initImpl( Iter i, Iter end, VigraFalseType /*isIntegral*/)
858 {
859  this->size_ = std::distance(i, end);
860  capacity_ = this->size_;
861  this->data_ = reserve_raw(capacity_);
862  if(this->size_ > 0)
863  std::uninitialized_copy(i, end, this->data_);
864 }
865 
866 template <class T, class Alloc>
867 inline void
868 ArrayVector<T, Alloc>::swap(this_type & rhs)
869 {
870  std::swap(this->size_, rhs.size_);
871  std::swap(capacity_, rhs.capacity_);
872  std::swap(this->data_, rhs.data_);
873 }
874 
875 template <class T, class Alloc>
876 inline void
877 ArrayVector<T, Alloc>::deallocate(pointer data, size_type size)
878 {
879  if(data)
880  {
881  detail::destroy_n(data, (int)size);
882  alloc_.deallocate(data, size);
883  }
884 }
885 
886 template <class T, class Alloc>
887 inline typename ArrayVector<T, Alloc>::pointer
888 ArrayVector<T, Alloc>::reserve_raw(size_type capacity)
889 {
890  pointer data = 0;
891  if(capacity)
892  {
893  data = alloc_.allocate(capacity);
894  }
895  return data;
896 }
897 
898 } // namespace vigra
899 
900 namespace std {
901 
902 template <class T>
903 ostream & operator<<(ostream & s, vigra::ArrayVectorView<T> const & a)
904 {
905  for(int k=0; k<(int)a.size()-1; ++k)
906  s << a[k] << ", ";
907  if(a.size())
908  s << a.back();
909  return s;
910 }
911 
912 } // namespace std
913 
914 #undef VIGRA_ASSERT_INSIDE
915 #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.8.0 (Wed Sep 26 2012)