Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component bdlt_calendarreverseiteratoradapter
[Package bdlt]

Provide reverse iterator adapter for calendar iterators. More...

Namespaces

namespace  bdlt

Detailed Description

Outline
Purpose:
Provide reverse iterator adapter for calendar iterators.
Classes:
bdlt::CalendarReverseIteratorAdapter calendar reverse iterator adapter
See also:
Component bdlt_calendar, Component bdlt_packedcalendar
Description:
This component provides a template, bdlt::CalendarReverseIteratorAdapter, that can be used to adapt a calendar iterator to be a reverse iterator (see bdlt_calendar and bdlt_packedcalendar). Calendar iterators cannot return a reference to an underlying element of the calendar and hence cannot be used with bsl::reverse_iterator. The reverse iterator adapter defined in this component provides a subset of the bsl::reverse_iterator interface that can be used with the calendar iterators defined in bdlt. Specifically, the types value_type, difference_type, pointer, and reference are defined but iterator_category is not defined (since this is not a fully-compliant iterator). Furthermore, the methods appropriate for random-access iterators are not included (e.g., operator+=).
Limitation:
bdlt::CalendarReverseIteratorAdapter is not a fully-compliant implementation of std::reverse_iterator according to the C++ standard. It is an implementation of the minimum functionality needed to support the public iterators in the bdlt_calendar and bdlt_packedcalendar components. Within that limitation, it is a subset implementation of bsl::reverse_iterator. Specifically, iterator_category is not defined for this adapter and the methods of a bsl::reverse_iterator relevant only to random-access compliant ITERATOR types are omitted.
Usage:
This section illustrates intended use of this component.
Example 1: Basic Use of bdlt::CalendarReverseIteratorAdapter:
In this example, we will use the bdlt::CalendarReverseIteratorAdapter to traverse an iterable container type. Specifically, we will create an array of struct values, implement a bidirectional iterator class that is a forward iterator for this array, and then use bdlt::CalendarReverseIteratorAdapter to provide a reverse iterator that will be used to traverse the array.
First, we define a bidirectional iterator class:
  template <class TYPE>
  class Iterator {
      // This 'class' basically behaves as a pointer to the (template
      // parameter) 'TYPE' with 4 types defined to allow the use of
      // 'bdlt::CalendarReverseIteratorAdapter' with this 'class'.  Note that
      // this 'class' supports only a subset of the functionality that a
      // pointer would, but this subset covers all the functionality that a
      // 'bdlt::CalendarReverseIteratorAdapter' needs.

      // DATA
      TYPE *d_ptr;  // pointer to the element referred to by this iterator

      // FRIENDS
      template <class OTHER>
      friend bool operator==(const Iterator<OTHER>&, const Iterator<OTHER>&);

    public:
      // PUBLIC TYPES
      typedef TYPE   value_type;
      typedef int    difference_type;
      typedef TYPE  *pointer;
      typedef TYPE&  reference;

      // CREATORS
      Iterator()
          // Create an 'Iterator' object having the default value.
      : d_ptr(0)
      {
      }

      Iterator(TYPE *value)                                       // IMPLICIT
          // Create an 'Iterator' object from the specified 'value'.
      : d_ptr(value)
      {
      }

      // Iterator(const Iterator&) = default;

      // ~Iterator() = default;

      // MANIPULATORS
      // Iterator& operator=(const Iterator&) = default;

      Iterator& operator++()
          // Increment to the next element in the iteration sequence, and
          // return a reference providing modifiable access to this iterator.
          // The behavior is undefined if, on entry, this iterator has the
          // past-the-end value for an iterator over the underlying sequence.
      {
          ++d_ptr;
          return *this;
      }

      Iterator& operator--()
          // Decrement to the previous element in the iteration sequence, and
          // return a reference providing modifiable access to this iterator.
          // The behavior is undefined if, on entry, this iterator has the
          // same value as an iterator at the start of the underlying
          // sequence.
      {
          --d_ptr;
          return *this;
      }

      // ACCESSORS
      reference operator*() const
          // Return a reference to the element referred to by this iterator.
          // The behavior is undefined unless this iterator is within the
          // bounds of the underlying sequence.
      {
          return *d_ptr;
      }

      pointer operator->() const
          // Return a pointer to the element referred to by this iterator.
          // The behavior is undefined unless this iterator is within the
          // bounds of the underlying sequence.
      {
          return d_ptr;
      }

      Iterator operator+(bsl::ptrdiff_t offset) const
          // Return an iterator referencing the location at the specified
          // 'offset' from the element referenced by this iterator.  The
          // behavior is undefined unless the resultant iterator is within
          // the bounds of the underlying sequence.
      {
          return Iterator(d_ptr + offset);
      }
  };

  // FREE OPERATORS
  template <class TYPE>
  inline
  bool operator==(const Iterator<TYPE>& lhs,  const Iterator<TYPE>& rhs)
      // Return 'true' if the specified 'lhs' iterator has the same value as
      // the specified 'rhs' iterator, and 'false' otherwise.  Two iterators
      // have the same value if they refer to the same element, or both have
      // the past-the-end value for am iterator over the underlying iteration
      // sequence.  The behavior is undefined unless 'lhs' and 'rhs' refer to
      // the same underlying sequence.
  {
      return lhs.d_ptr == rhs.d_ptr;
  }

  template <class TYPE>
  inline
  bool operator!=(const Iterator<TYPE>& lhs, const Iterator<TYPE>& rhs)
      // Return 'true' if the specified 'lhs' iterator does not have the same
      // value as the specified 'rhs' iterator, and 'false' otherwise.  Two
      // iterators do not have the same value if (1) they do not refer to the
      // same element and (2) both do not have the past-the-end value for an
      // iterator over the underlying iteration sequence.  The behavior is
      // undefined unless 'lhs' and 'rhs' refer to the same underlying
      // sequence.
  {
      return !(lhs == rhs);
  }
Then, we define struct S, the type that will be referred to by the Iterator type:
  struct S {
      char d_c;
      int  d_i;
  };
The struct S has two data members. By creating an array of distinct S values, the state of an iterator referring to an element of this array can be easily verified by inspecting these two members.
Next, we define four (distinct) S values:
  const S s0 = { 'A', 3 };
  const S s1 = { 'B', 5 };
  const S s2 = { 'C', 7 };
  const S s3 = { 'D', 9 };
Then, we define s, an array of S values:
  S s[] = { s0, s1, s2, s3 };
  enum { NUM_S = sizeof s / sizeof *s };
Next, we define an iterator, sfBegin, referring to the first element of s and an iterator, sfEnd, having the past-the-end value for an iterator over s:
  Iterator<S> sfBegin(s + 0), sfEnd(s + NUM_S);
Then, for convenience we declare our reverse iterator type that will be used to traverse s in the reverse direction: Next, we declare begin and end reverse iterators to our range of S values:
  const Reverse rBegin(sfEnd), rEnd(sfBegin);
Now, we traverse our range in the reverse direction, from rBegin to rEnd, streaming out the contents of the S values as we go:
  bsl::ostringstream stream;
  for (Reverse it = rBegin; rEnd != it; ++it) {
      stream << (rBegin == it ? "" : ", ")
             << "{ "
             << it->d_c
             << ", "
             << it->d_i
             << " }";
  }
  stream << bsl::flush;
Finally, we verify the contents of the range output:
  assert(stream.str() == "{ D, 9 }, { C, 7 }, { B, 5 }, { A, 3 }");