Tuesday, 31 March 2015

STL-Iterator adaptors in C++

STL-Iterator adaptors in Cpp with code examples:

Reverse iterators:

Bidirectional and random access iterators have corresponding reverse iterator adaptors that iterate through the data structure in the opposite direction. They have the same signatures as the corresponding iterators.
The fundamental relation between a reverse iterator and its corresponding iterator i is established by the Identity
 &*(reverse_iterator(iIndex)) == &*( iIndex - 1)

This mapping is dictated by the fact that while there is always a pointer past the end of an array, there might not be a valid pointer before the beginning of an array.

A copy of the original iterator (the base iterator) is kept internally and used to reflect the operations performed on the reverse_iterator: whenever the reverse_iterator is incremented, its base iterator is decreased, and vice versa. A copy of the base iterator with the current state can be obtained at any time by calling member base.

Notice however that when an iterator is reversed, the reversed version does not point to the same element in the range, but to the one preceding it. This is so, in order to arrange for the past-the-end element of a range: An iterator pointing to a past-the-end element in a range, when reversed, is pointing to the last element (not past it) of the range (this would be the first element of the reversed range). And if an iterator to the first element in a range is reversed, the reversed iterator points to the element before the first element (this would be the past-the-end element of the reversed range).

template <class Bi-Itters, class Test, class ClsRef = Test&, class ClsDistCal = ocDist>
class ClsBi-IttersRev : public bidirectional_iterator<Test, ClsDistCal> { typedef ClsBi-IttersRev<Bi-Itters, Test, ClsRef, ClsDistCal> ocRev; friend bool operator==(const ocRev& ocTemp, const ocRev& ocDistTest); protected: Bi-Itters ocIndex; public: ClsBi-IttersRev () {} ClsBi-IttersRev(Bi-Itters ocTemp) : ocIndex(ocTemp) {} Bi-Itters base() { return ocIndex; } ClsRef operator*() const { Bi-Itters biTemp = ocIndex; return *--biTemp; } ocRev& operator++() { --ocIndex; return *this; } ocRev operator++(int) { ocRev biTemp = *this; --ocIndex; return biTemp; } ocRev& operator--() { ++ocIndex; return *this; } ocRev operator--(int) { ocRev biTemp = *this; ++ocIndex; return biTemp; } }; template <class Bi-Itters, class Test, class ClsRef, class ClsDistCal> inline bool operator==( const ClsBi-IttersRev<Bi-Itters, Test, ClsRef, ClsDistCal>& ocTemp, const ClsBi-IttersRev<Bi-Itters, Test, ClsRef, ClsDistCal>& ocDistTest) { return ocTemp.ocIndex == ocDistTest.ocIndex; } template <class RandomAccessIterator, class Test, class ClsRef = Test&, class ClsDistCal = ocDist> class reverse_iterator : public random_access_iterator<Test, ClsDistCal> { typedef reverse_iterator<RandomAccessIterator, Test, ClsRef, ClsDistCal> ocRev; friend bool operator==(const ocRev& ocTemp, const ocRev& ocDistTest); friend bool operator<(const ocRev& ocTemp, const ocRev& ocDistTest); friend ClsDistCal operator-(const ocRev& ocTemp, const ocRev& ocDistTest); friend ocRev operator+(ClsDistCal ocDistance, const ocRev& ocTemp); protected: RandomAccessIterator ocIndex; public: reverse_iterator() {} reverse_iterator(RandomAccessIterator ocTemp) : ocIndex(ocTemp) {} RandomAccessIterator base() { return ocIndex; } ClsRef operator*() const { RandomAccessIterator biTemp = ocIndex; return *--biTemp; } ocRev& operator++() { --ocIndex; return *this; } ocRev operator++(int) { ocRev biTemp = *this; --ocIndex; return biTemp; } ocRev& operator--() { ++ocIndex; return *this; } ocRev operator--(int) { ocRev biTemp = *this; ++ocIndex; return biTemp; } ocRev operator+(ClsDistCal ocDistance) const { return ocRev(ocIndex - ocDistance); } ocRev& operator+=(ClsDistCal ocDistance) { ocIndex -= ocDistance; return *this; } ocRev operator-(ClsDistCal ocDistance) const { return ocRev(ocIndex + ocDistance); } ocRev& operator-=(ClsDistCal ocDistance) { ocIndex += ocDistance; return *this; } ClsRef operator[](ClsDistCal ocDistance) { return *(*this + ocDistance); } }; template <class RandomAccessIterator, class Test, class ClsRef, class ClsDistCal> inline bool operator==( const reverse_iterator<RandomAccessIterator, Test, ClsRef, ClsDistCal>& ocTemp, const reverse_iterator<RandomAccessIterator, Test, ClsRef, ClsDistCal>& ocDistTest) { return ocTemp.ocIndex == ocDistTest.ocIndex; } template <class RandomAccessIterator, class Test, class ClsRef, class ClsDistCal> inline bool operator<( const reverse_iterator<RandomAccessIterator, Test, ClsRef, ClsDistCal>& ocTemp, const reverse_iterator<RandomAccessIterator, Test, ClsRef, ClsDistCal>& ocDistTest) { return ocDistTest.ocIndex < ocTemp.ocIndex; } template <class RandomAccessIterator, class Test, class ClsRef, class ClsDistCal> inline ClsDistCal operator-( const reverse_iterator<RandomAccessIterator, Test, ClsRef, ClsDistCal>& ocTemp, const reverse_iterator<RandomAccessIterator, Test, ClsRef, ClsDistCal>& ocDistTest) { return ocDistTest.ocIndex - ocTemp.ocIndex; } template <class RandomAccessIterator, class Test, class ClsRef, class ClsDistCal> inline reverse_iterator<RandomAccessIterator, Test, ClsRef, ClsDistCal> operator+(   ClsDistCal ocDistance, const reverse_iterator<RandomAccessIterator, Test, ClsRef, ClsDistCal>& ocTemp) { return reverse_iterator<RandomAccessIterator, Test, ClsRef, ClsDistCal> (ocTemp.ocIndex - ocDistance); }

Insert iterators:

Insert iterators are special output iterators designed to allow algorithms that usually overwrite elements   to instead insert new elements at a specific position in the container.
The container needs to have an insert member function (such as most standard containers).
Using the assignment operator on the insert_iterator (both while being dereferenced or not), causes the container to expand by one element, which is initialized to the value assigned.
The other typical operators of an output iterator are also defined for insert_iterator but have no effect: all values assigned are inserted at the beginning of the container.

To make it possible to deal with insertion in the same way as writing into an array, a special kind of iterator adaptors, called insert iterators, are provided in the library. With regular iterator classes,
while (first != last) *result++ = *first++; 

causes a range [first, last) to be copied into a range starting with result.

template <class TempContianers>

class back_insert_iterator : public Out_iter {

protected:

TempContianers& TempContianers;

public:

back_insert_iterator (TempContianers& ocContainer) : TempContianers(ocContainer)

{}

back_insert_iterator<TempContianers>& operator= (const TempContianers::value_type& ocValue)

{

TempContianers.push_back (ocValue);

return *this;

}

back_insert_iterator<TempContianers>& operator*() { return *this; }

back_insert_iterator<TempContianers>& operator++() { return *this; }

back_insert_iterator<TempContianers>& operator++(int) { return *this; }

};

template <class TempContianers>

back_insert_iterator<TempContianers> back_inserter(TempContianers& ocContainer)

  { return back_insert_iterator<TempContianers>(ocContainer); }

template <class TempContianers>

class front_insert_iterator : public Out_iter

{

protected:

TempContianers& TempContianers;

public:

front_insert_iterator(TempContianers& ocContainer) : TempContianers(ocContainer)

{}

front_insert_iterator<TempContianers>& operator=(const TempContianers::value_type& ocValue)

{

TempContianers.push_front(ocValue);

return *this;

}

front_insert_iterator<TempContianers>& operator*() { return *this; }

front_insert_iterator<TempContianers>& operator++() { return *this; }

front_insert_iterator<TempContianers>& operator++(int) { return *this; }

};

template <class TempContianers>

front_insert_iterator<TempContianers> front_inserter(TempContianers& ocContainer)

  { return front_insert_iterator<TempContianers>(ocContainer); }

template <class TempContianers>

class insert_iterator : public Out_iter

{

protected:

TempContianers& TempContianers;

TempContianers::iterator ocIter;

public:

insert_iterator(TempContianers& ocContainer, TempContianers::iterator iIndexIter) : TempContianers(ocContainer), ocIter(iIndexIter)

  {}

insert_iterator<TempContianers>& operator=(const TempContianers::value_type& ocValue)

{

ocIter = TempContianers.insert(ocIter, ocValue);

++ocIter;

return *this;

}

insert_iterator<TempContianers>& operator*() { return *this; }

insert_iterator<TempContianers>& operator++() { return *this; }

insert_iterator<TempContianers>& operator++(int) { return *this; }

};

template <class TempContianers, class Iterator>

insert_iterator<TempContianers> inserter(TempContianers& ocContainer, Iterator iIndexIter)

  { return insert_iterator<TempContianers>(ocContainer, TempContianers::iterator(iIndexIter)); }


Raw storage iterator:

This iterator class operates on uninitialized memory blocks.
Regular iterators operate on a certain type of objects, which have already been constructed. A raw_storage_iterator wraps one of these regular iterators into a special output iterator, which constructs objects at the location being pointed before being written.
raw_storage_iterator is provided to enable algorithms to store the results into uninitialized memory.
The formal template parameter OutputIterator is required to have construct(OutputIterator, const
T&) defined.
 template <class Out_Iter, class TempCLs>

class raw_storage_iterator : public output_iterator {

protected:

Out_Iter ocOutIter;

public:

raw_storage_iterator(Out_Iter ocOut) : ocOutIter(ocOut) {}

raw_storage_iterator<Out_Iter, TempCLs>& operator*() { return *this; }

raw_storage_iterator<Out_Iter, TempCLs>& operator=(const TempCLs& element) {

construct(ocOutIter, element);

return *this;

}

raw_storage_iterator<Out_Iter, TempCLs>& operator++() {

++ocOutIter;

return *this;

}

raw_storage_iterator<Out_Iter, TempCLs> operator++(int) {

raw_storage_iterator<Out_Iter, TempCLs> ocRawStorage = *this;

++ocOutIter;

return ocRawStorage;

}

};



No comments: