36 #ifndef VIGRA_ARRAY_VECTOR_HXX
37 #define VIGRA_ARRAY_VECTOR_HXX
41 #include "numerictraits.hxx"
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");
51 #define VIGRA_ASSERT_INSIDE(diff)
57 template <
class T,
class Alloc = std::allocator<T> >
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;
158 if(data_ != rhs.data_)
180 if(data_ != rhs.data_)
202 vigra_precondition(begin <= end && end <= size_,
203 "ArrayVectorView::subarray(): Limits out of range.");
204 return this_type(end-begin, data_ + begin);
209 inline const_pointer
data()
const
237 inline const_iterator
end()
const
258 inline const_iterator
cend()
const
267 return (reverse_iterator(
end()));
272 inline const_reverse_iterator
rbegin()
const
274 return (const_reverse_iterator(
end()));
281 return (reverse_iterator(
begin()));
286 inline const_reverse_iterator
rend()
const
288 return (const_reverse_iterator(
begin()));
295 return (const_reverse_iterator(
end()));
300 inline const_reverse_iterator
crend()
const
302 return (const_reverse_iterator(
begin()));
323 return data_[size_-1];
330 return data_[size_-1];
337 VIGRA_ASSERT_INSIDE(i);
345 VIGRA_ASSERT_INSIDE(i);
382 return p >= 0 && p < size_;
407 else if(data_ != rhs.data_)
416 if(size() != rhs.
size())
418 for(size_type k=0; k<size(); ++k)
419 if(data_[k] != rhs[k])
428 vigra_precondition (size() == rhs.size(),
429 "ArrayVectorView::copy(): shape mismatch.");
433 if(data_ <= rhs.data())
435 std::copy(rhs.begin(), rhs.end(), begin());
439 std::copy_backward(rhs.begin(), rhs.end(), end());
446 ArrayVectorView <T>::copyImpl(
const ArrayVectorView <U>& rhs)
448 vigra_precondition (size() == rhs.size(),
449 "ArrayVectorView::copy(): shape mismatch.");
450 std::copy(rhs.begin(), rhs.end(), begin());
456 ArrayVectorView <T>::swapDataImpl(
const ArrayVectorView <U>& rhs)
458 vigra_precondition (size () == rhs.size() (),
459 "ArrayVectorView::swapData(): size mismatch.");
462 if(data_ + size_ <= rhs.data_ || rhs.data_ + size_ <= data_)
464 for(size_type k=0; k<size_; ++k)
465 std::swap(data_[k], rhs.data_[k]);
469 ArrayVector<T> t(*
this);
511 template <
class T,
class Alloc >
513 :
public ArrayVectorView<T>
515 typedef ArrayVector<T, Alloc> this_type;
516 enum { minimumCapacity = 2, resizeFactor = 2 };
519 typedef ArrayVectorView<T> view_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;
536 capacity_(minimumCapacity),
539 this->data_ = reserve_raw(capacity_);
542 explicit ArrayVector(Alloc
const & alloc)
544 capacity_(minimumCapacity),
547 this->data_ = reserve_raw(capacity_);
550 explicit ArrayVector( size_type
size, Alloc
const & alloc = Alloc())
554 initImpl(size, value_type(), VigraTrueType());
557 ArrayVector( size_type size, value_type
const & initial, Alloc
const & alloc = Alloc())
561 initImpl(size, initial, VigraTrueType());
565 ArrayVector( this_type
const & rhs )
569 initImpl(rhs.begin(), rhs.end(), VigraFalseType());
573 explicit ArrayVector( ArrayVectorView<U>
const & rhs, Alloc
const & alloc = Alloc() )
577 initImpl(rhs.begin(), rhs.end(), VigraFalseType());
580 template <
class InputIterator>
581 ArrayVector(InputIterator i, InputIterator
end)
583 initImpl(i, end,
typename NumericTraits<InputIterator>::isIntegral());
586 template <
class InputIterator>
587 ArrayVector(InputIterator i, InputIterator end, Alloc
const & alloc)
590 initImpl(i, end,
typename NumericTraits<InputIterator>::isIntegral());
593 this_type & operator=( this_type
const & rhs )
597 if(this->size_ == rhs.size_)
608 this_type & operator=( ArrayVectorView<U>
const & rhs);
612 deallocate(this->data_, this->size_, this->capacity_);
617 void push_back( value_type
const & t );
619 iterator insert(iterator p, value_type
const & v);
621 iterator insert(iterator p, size_type n, value_type
const & v);
623 template <
class InputIterator>
624 iterator insert(iterator p, InputIterator i, InputIterator iend);
626 iterator erase(iterator p);
628 iterator erase(iterator p, iterator q);
632 pointer reserveImpl(
bool dealloc, size_type new_capacity );
634 pointer reserveImpl(
bool dealloc);
641 void reserve( size_type new_capacity )
643 reserveImpl(
true, new_capacity);
646 void resize( size_type new_size, value_type
const & initial );
648 void resize( size_type new_size )
650 resize(new_size, value_type());
653 size_type capacity()
const
658 void swap(this_type & rhs);
662 void deallocate(pointer
data, size_type size, size_type capacity);
664 pointer reserve_raw(size_type capacity);
666 void initImpl( size_type size, value_type
const & initial, VigraTrueType );
668 template <
class Iter>
669 void initImpl( Iter i, Iter end, VigraFalseType );
671 template <
class Iter>
672 void initImpl( Iter i, Iter end, Error_NumericTraits_not_specialized_for_this_case)
674 initImpl(i, end, VigraFalseType());
681 template <
class T,
class Alloc>
683 ArrayVector<T, Alloc> & ArrayVector<T, Alloc>::operator=( ArrayVectorView<U>
const & rhs )
685 if(this->size_ == rhs.size())
695 template <
class T,
class Alloc>
696 inline void ArrayVector<T, Alloc>::pop_back()
699 alloc_.destroy(this->data_ + this->size_);
702 template <
class T,
class Alloc>
703 inline void ArrayVector<T, Alloc>::push_back( value_type
const & t )
705 size_type old_capacity = this->capacity_;
706 pointer old_data = reserveImpl(
false);
707 alloc_.construct(this->data_ + this->size_, t);
710 deallocate(old_data, this->size_, old_capacity);
714 template <
class T,
class Alloc>
715 inline void ArrayVector<T, Alloc>::clear()
717 detail::destroy_n(this->data_, this->size_);
721 template <
class T,
class Alloc>
722 typename ArrayVector<T, Alloc>::iterator
723 ArrayVector<T, Alloc>::insert(iterator p, value_type
const & v)
725 difference_type pos = p - this->begin();
729 p = this->begin() + pos;
733 T lastElement = this->back();
734 push_back(lastElement);
735 p = this->begin() + pos;
736 std::copy_backward(p, this->end() - 2, this->end() - 1);
742 template <
class T,
class Alloc>
743 typename ArrayVector<T, Alloc>::iterator
744 ArrayVector<T, Alloc>::insert(iterator p, size_type n, value_type
const & v)
746 difference_type pos = p - this->begin();
747 size_type new_size = this->size() + n;
748 if(new_size > capacity_)
750 size_type new_capacity = std::max(new_size, resizeFactor*capacity_);
751 pointer new_data = reserve_raw(new_capacity);
754 std::uninitialized_copy(this->begin(), p, new_data);
755 std::uninitialized_fill(new_data + pos, new_data + pos + n, v);
756 std::uninitialized_copy(p, this->end(), new_data + pos + n);
760 alloc_.deallocate(new_data, new_capacity);
763 deallocate(this->data_, this->size_, this->capacity_);
764 capacity_ = new_capacity;
765 this->data_ = new_data;
767 else if(pos + n > this->size_)
769 size_type diff = pos + n - this->size_;
770 std::uninitialized_copy(p, this->end(), this->end() + diff);
771 std::uninitialized_fill(this->end(), this->end() + diff, v);
772 std::fill(p, this->end(), v);
776 size_type diff = this->size_ - (pos + n);
777 std::uninitialized_copy(this->end() - n, this->end(), this->end());
778 std::copy_backward(p, p + diff, this->end());
779 std::fill(p, p + n, v);
781 this->size_ = new_size;
782 return this->begin() + pos;
785 template <
class T,
class Alloc>
786 template <
class InputIterator>
787 typename ArrayVector<T, Alloc>::iterator
788 ArrayVector<T, Alloc>::insert(iterator p, InputIterator i, InputIterator iend)
790 size_type n = std::distance(i, iend);
791 size_type pos = p - this->begin();
792 size_type new_size = this->size() + n;
793 if(new_size > capacity_)
795 size_type new_capacity = std::max(new_size, resizeFactor*capacity_);
796 pointer new_data = reserve_raw(new_capacity);
799 std::uninitialized_copy(this->begin(), p, new_data);
800 std::uninitialized_copy(i, iend, new_data + pos);
801 std::uninitialized_copy(p, this->end(), new_data + pos + n);
805 alloc_.deallocate(new_data, new_capacity);
808 deallocate(this->data_, this->size_, this->capacity_);
809 capacity_ = new_capacity;
810 this->data_ = new_data;
812 else if(pos + n > this->size_)
814 size_type diff = pos + n - this->size_;
815 std::uninitialized_copy(p, this->end(), this->end() + diff);
816 InputIterator split = i;
817 std::advance(split, n - diff);
818 std::uninitialized_copy(split, iend, this->end());
819 std::copy(i, split, p);
823 size_type diff = this->size_ - (pos + n);
824 std::uninitialized_copy(this->end() - n, this->end(), this->end());
825 std::copy_backward(p, p + diff, this->end());
826 std::copy(i, iend, p);
828 this->size_ = new_size;
829 return this->begin() + pos;
832 template <
class T,
class Alloc>
833 typename ArrayVector<T, Alloc>::iterator
834 ArrayVector<T, Alloc>::erase(iterator p)
836 std::copy(p+1, this->end(), p);
841 template <
class T,
class Alloc>
842 typename ArrayVector<T, Alloc>::iterator
843 ArrayVector<T, Alloc>::erase(iterator p, iterator q)
845 std::copy(q, this->end(), p);
846 difference_type eraseCount = q - p;
847 detail::destroy_n(this->end() - eraseCount, eraseCount);
848 this->size_ -= eraseCount;
852 template <
class T,
class Alloc>
853 typename ArrayVector<T, Alloc>::pointer
854 ArrayVector<T, Alloc>::reserveImpl(
bool dealloc, size_type new_capacity)
856 if(new_capacity <= capacity_)
858 pointer new_data = reserve_raw(new_capacity),
859 old_data = this->data_;
861 std::uninitialized_copy(old_data, old_data+this->size_, new_data);
862 this->data_ = new_data;
865 this->capacity_ = new_capacity;
868 deallocate(old_data, this->size_, this->capacity_);
869 this->capacity_ = new_capacity;
873 template <
class T,
class Alloc>
874 inline typename ArrayVector<T, Alloc>::pointer
875 ArrayVector<T, Alloc>::reserveImpl(
bool dealloc)
878 return reserveImpl(dealloc, minimumCapacity);
879 else if(this->size_ == capacity_)
880 return reserveImpl(dealloc, resizeFactor*capacity_);
885 template <
class T,
class Alloc>
887 ArrayVector<T, Alloc>::resize( size_type new_size, value_type
const & initial)
889 if(new_size < this->size_)
890 erase(this->begin() + new_size, this->end());
891 else if(this->size_ < new_size)
893 insert(this->end(), new_size - this->size(), initial);
897 template <
class T,
class Alloc>
899 ArrayVector<T, Alloc>::initImpl( size_type size, value_type
const & initial, VigraTrueType )
903 this->data_ = reserve_raw(capacity_);
905 std::uninitialized_fill(this->data_, this->data_+this->size_, initial);
908 template <
class T,
class Alloc>
909 template <
class Iter>
911 ArrayVector<T, Alloc>::initImpl( Iter i, Iter end, VigraFalseType )
913 this->size_ = std::distance(i, end);
914 capacity_ = this->size_;
915 this->data_ = reserve_raw(capacity_);
917 detail::uninitializedCopy(i, end, this->data_);
920 template <
class T,
class Alloc>
922 ArrayVector<T, Alloc>::swap(this_type & rhs)
924 std::swap(this->size_, rhs.size_);
925 std::swap(capacity_, rhs.capacity_);
926 std::swap(this->data_, rhs.data_);
929 template <
class T,
class Alloc>
931 ArrayVector<T, Alloc>::deallocate(pointer data, size_type size, size_type capacity)
935 detail::destroy_n(data, size);
936 alloc_.deallocate(data, capacity);
940 template <
class T,
class Alloc>
941 inline typename ArrayVector<T, Alloc>::pointer
942 ArrayVector<T, Alloc>::reserve_raw(size_type capacity)
947 data = alloc_.allocate(capacity);
957 ostream & operator<<(ostream & s, vigra::ArrayVectorView<T>
const & a)
959 for(std::ptrdiff_t k=0; k<(std::ptrdiff_t)a.size()-1; ++k)
968 #undef VIGRA_ASSERT_INSIDE
iterator end()
Definition: array_vector.hxx:244
reference back()
Definition: array_vector.hxx:321
void swapData(this_type rhs)
Definition: array_vector.hxx:178
this_type & operator=(ArrayVectorView< U > const &rhs)
Definition: array_vector.hxx:137
ArrayVectorView(size_type size, pointer const &data)
Definition: array_vector.hxx:107
bool empty() const
Definition: array_vector.hxx:351
Definition: array_vector.hxx:76
const_iterator begin() const
Definition: array_vector.hxx:223
reverse_iterator rend()
Definition: array_vector.hxx:279
const_reverse_iterator crend() const
Definition: array_vector.hxx:300
bool isInside(difference_type const &p) const
Definition: array_vector.hxx:380
const_reverse_iterator rbegin() const
Definition: array_vector.hxx:272
const_reverse_iterator crbegin() const
Definition: array_vector.hxx:293
const_reference back() const
Definition: array_vector.hxx:328
ArrayVectorView & operator=(ArrayVectorView const &rhs)
void copy(ArrayVectorView< U > const &rhs)
Definition: array_vector.hxx:168
reference operator[](difference_type i)
Definition: array_vector.hxx:335
Definition: array_vector.hxx:58
reference front()
Definition: array_vector.hxx:307
ArrayVectorView()
Definition: array_vector.hxx:99
bool operator!=(ArrayVectorView< U > const &rhs) const
Definition: array_vector.hxx:373
void init(U const &initial)
Definition: array_vector.hxx:146
pointer data()
Definition: array_vector.hxx:216
const_reference front() const
Definition: array_vector.hxx:314
this_type subarray(size_type begin, size_type end) const
Definition: array_vector.hxx:200
iterator begin()
Definition: array_vector.hxx:230
const_iterator cend() const
Definition: array_vector.hxx:258
const_iterator cbegin() const
Definition: array_vector.hxx:251
T value_type
Definition: array_vector.hxx:83
void copy(this_type const &rhs)
Definition: array_vector.hxx:156
reverse_iterator rbegin()
Definition: array_vector.hxx:265
const_iterator end() const
Definition: array_vector.hxx:237
const_pointer data() const
Definition: array_vector.hxx:209
size_type size() const
Definition: array_vector.hxx:358
ArrayVectorView(this_type const &rhs)
Definition: array_vector.hxx:114
void swapData(ArrayVectorView< U > rhs)
Definition: array_vector.hxx:190
bool operator==(ArrayVectorView< U > const &rhs) const
Definition: array_vector.hxx:414
const_reference operator[](difference_type i) const
Definition: array_vector.hxx:343
const_reverse_iterator rend() const
Definition: array_vector.hxx:286