[ 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> <<a href="array__vector_8hxx-source.html">vigra/array_vector.hxx</a>><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> refering 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 refering to the first array element.
222  */
223  inline const_iterator begin() const
224  {
225  return data();
226  }
227 
228  /** Get iterator refering 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 lagacy 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> <<a href="array__vector_8hxx-source.html">vigra/array_vector.hxx</a>><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:
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  std::uninitialized_copy(this->begin(), p, new_data);
708  std::uninitialized_fill(new_data + pos, new_data + pos + n, v);
709  std::uninitialized_copy(p, this->end(), new_data + pos + n);
710  deallocate(this->data_, this->size_);
711  capacity_ = new_capacity;
712  this->data_ = new_data;
713  }
714  else if(pos + n >= this->size_)
715  {
716  size_type diff = pos + n - this->size_;
717  std::uninitialized_copy(p, this->end(), this->end() + diff);
718  std::uninitialized_fill(this->end(), this->end() + diff, v);
719  std::fill(p, this->end(), v);
720  }
721  else
722  {
723  size_type diff = this->size_ - (pos + n);
724  std::uninitialized_copy(this->end() - n, this->end(), this->end());
725  std::copy_backward(p, p + diff, this->end());
726  std::fill(p, p + n, v);
727  }
728  this->size_ = new_size;
729  return this->begin() + pos;
730 }
731 
732 template <class T, class Alloc>
733 template <class InputIterator>
734 typename ArrayVector<T, Alloc>::iterator
735 ArrayVector<T, Alloc>::insert(iterator p, InputIterator i, InputIterator iend)
736 {
737  size_type n = iend - i;
738  size_type pos = p - this->begin();
739  size_type new_size = this->size() + n;
740  if(new_size >= capacity_)
741  {
742  size_type new_capacity = std::max(new_size, resizeFactor*capacity_);
743  pointer new_data = reserve_raw(new_capacity);
744  std::uninitialized_copy(this->begin(), p, new_data);
745  std::uninitialized_copy(i, iend, new_data + pos);
746  std::uninitialized_copy(p, this->end(), new_data + pos + n);
747  deallocate(this->data_, this->size_);
748  capacity_ = new_capacity;
749  this->data_ = new_data;
750  }
751  else if(pos + n >= this->size_)
752  {
753  size_type diff = pos + n - this->size_;
754  std::uninitialized_copy(p, this->end(), this->end() + diff);
755  std::uninitialized_copy(iend - diff, iend, this->end());
756  std::copy(i, iend - diff, p);
757  }
758  else
759  {
760  size_type diff = this->size_ - (pos + n);
761  std::uninitialized_copy(this->end() - n, this->end(), this->end());
762  std::copy_backward(p, p + diff, this->end());
763  std::copy(i, iend, p);
764  }
765  this->size_ = new_size;
766  return this->begin() + pos;
767 }
768 
769 template <class T, class Alloc>
770 typename ArrayVector<T, Alloc>::iterator
771 ArrayVector<T, Alloc>::erase(iterator p)
772 {
773  std::copy(p+1, this->end(), p);
774  pop_back();
775  return p;
776 }
777 
778 template <class T, class Alloc>
779 typename ArrayVector<T, Alloc>::iterator
780 ArrayVector<T, Alloc>::erase(iterator p, iterator q)
781 {
782  std::copy(q, this->end(), p);
783  difference_type eraseCount = q - p;
784  detail::destroy_n(this->end() - eraseCount, eraseCount);
785  this->size_ -= eraseCount;
786  return p;
787 }
788 
789 template <class T, class Alloc>
790 inline void
791 ArrayVector<T, Alloc>::reserve( size_type new_capacity )
792 {
793  if(new_capacity <= capacity_)
794  return;
795  pointer new_data = reserve_raw(new_capacity);
796  if(this->size_ > 0)
797  std::uninitialized_copy(this->data_, this->data_+this->size_, new_data);
798  deallocate(this->data_, this->size_);
799  this->data_ = new_data;
800  capacity_ = new_capacity;
801 }
802 
803 template <class T, class Alloc>
804 inline void
805 ArrayVector<T, Alloc>::reserve()
806 {
807  if(capacity_ == 0)
808  reserve(minimumCapacity);
809  else if(this->size_ == capacity_)
810  reserve(resizeFactor*capacity_);
811 }
812 
813 template <class T, class Alloc>
814 inline void
815 ArrayVector<T, Alloc>::resize( size_type new_size, value_type const & initial)
816 {
817  if(new_size < this->size_)
818  erase(this->begin() + new_size, this->end());
819  else if(this->size_ < new_size)
820  {
821  insert(this->end(), new_size - this->size(), initial);
822  }
823 }
824 
825 template <class T, class Alloc>
826 inline void
827 ArrayVector<T, Alloc>::initImpl( size_type size, value_type const & initial, VigraTrueType /*isIntegral*/)
828 {
829  this->size_ = size;
830  capacity_ = size;
831  this->data_ = reserve_raw(capacity_);
832  if(this->size_ > 0)
833  std::uninitialized_fill(this->data_, this->data_+this->size_, initial);
834 }
835 
836 template <class T, class Alloc>
837 template <class Iter>
838 inline void
839 ArrayVector<T, Alloc>::initImpl( Iter i, Iter end, VigraFalseType /*isIntegral*/)
840 {
841  this->size_ = std::distance(i, end);
842  capacity_ = this->size_;
843  this->data_ = reserve_raw(capacity_);
844  if(this->size_ > 0)
845  std::uninitialized_copy(i, end, this->data_);
846 }
847 
848 template <class T, class Alloc>
849 inline void
850 ArrayVector<T, Alloc>::swap(this_type & rhs)
851 {
852  std::swap(this->size_, rhs.size_);
853  std::swap(capacity_, rhs.capacity_);
854  std::swap(this->data_, rhs.data_);
855 }
856 
857 template <class T, class Alloc>
858 inline void
859 ArrayVector<T, Alloc>::deallocate(pointer data, size_type size)
860 {
861  if(data)
862  {
863  detail::destroy_n(data, (int)size);
864  alloc_.deallocate(data, size);
865  }
866 }
867 
868 template <class T, class Alloc>
869 inline typename ArrayVector<T, Alloc>::pointer
870 ArrayVector<T, Alloc>::reserve_raw(size_type capacity)
871 {
872  pointer data = 0;
873  if(capacity)
874  {
875  data = alloc_.allocate(capacity);
876  }
877  return data;
878 }
879 
880 } // namespace vigra
881 
882 namespace std {
883 
884 template <class T>
885 ostream & operator<<(ostream & s, vigra::ArrayVectorView<T> const & a)
886 {
887  for(int k=0; k<(int)a.size()-1; ++k)
888  s << a[k] << ", ";
889  if(a.size())
890  s << a.back();
891  return s;
892 }
893 
894 } // namespace std
895 
896 #undef VIGRA_ASSERT_INSIDE
897 #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.7.1 (Tue Jul 10 2012)