BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslstl_bidirectionaliterator

Detailed Description

Outline

Purpose

Provide a template to create STL-compliant bidirectional iterators.

Classes

Canonical header: bsl_iterator.h

See also
bslstl_iterator, bslstl_forwarditerator, bslstl_randomaccessiterator

Description

This component provides an iterator adaptor that, given an implementation class defining a core set of iterator functionality specified in the class level documentation, adapts it to provide an STL-compliant bidirectional iterator interface. bslstl::BidirectionalIterator meets the requirements of a bidirectional iterator described in the C++11 standard [24.2.7] under the tag "[bidirectional.iterators]". Include bsl_iterator.h to use this component.

Usage

In this section we show intended use of this component.

Example 1: Defining a Standard Compliant Bidirectional Iterator

Suppose we want to create a standard compliant bidirectional access iterator for a container.

First, we define an iterator, MyArrayIterator, that meets the requirements of the IMP_ITER template parameter of BidirectionalIterator class (see class level documentation), but does not meet the full set of requirements for a bidirectional iterator as defined by the C++ standard. Note that the following shows only the public interface required. Private members and additional methods that may be needed to implement this class are elided in this example:

/// This class implements the minimal requirements to implement a
/// bidirectional iterator using `bslstl::BidirectionalIterator`.
template <class VALUE>
class MyArrayIterator {
public:
// CREATORS
/// Create a `MyArrayIterator` object that does not refer to any
/// value.
MyArrayIterator();
/// Create a `MyArrayIterator` object having the same value
/// as the specified `original` object.
MyArrayIterator(const MyArrayIterator& original);
/// Destroy this object;
~MyArrayIterator();
// MANIPULATORS
/// Assign to this object the value of the specified `rhs` object,
/// and return a reference providing modifiable access to this
/// object.
MyArrayIterator& operator=(const MyArrayIterator& rhs);
/// Increment this object to refer to the next element in an array.
void operator++();
/// Decrement this object to refer to the previous element in an
/// array.
void operator--();
// ACCESSORS
// Return a reference providing modifiable access to the value (of
// the parameterized `VALUE` type) of the element referred to by
// this object.
VALUE& operator*() const;
};
template <class VALUE>
bool operator==(const MyArrayIterator<VALUE>&,
const MyArrayIterator<VALUE>&);

Notice that MyArrayIterator does not implement a complete standard compliant bidirectional iterator. It is missing methods such as operator+ and operator[].

Then, we define the interface for our container class template, MyFixedSizeArray. The implementation of the interface is elided for brevity:

/// This class implements a container that contains the parameterized
/// `SIZE` number of elements of the parameterized `VALUE` type.
template <class VALUE, int SIZE>
class MyFixedSizeArray {
// DATA
VALUE d_array[SIZE]; // storage of the container
public:
// PUBLIC TYPES
typedef VALUE value_type;

Now, we use BidirectionalIterator to create a standard compliant iterator for this container:

MyArrayIterator<VALUE> > iterator;
typedef bslstl::BidirectionalIterator<const VALUE,
MyArrayIterator<VALUE> >
const_iterator;
Definition bslstl_bidirectionaliterator.h:266

Notice that the implementation for const_iterator is MyArrayIterator<VALUE> and not MyArrayIterator<const VALUE>.

Next, we continue defining the rest of the class.

// CREATORS
/// Create a `MyFixedSizeArray` object having the parameterized
/// `SIZE` number of elements of the parameterized type `VALUE`.
//! MyFixedSizeArray() = default;
/// Create a `MyFixedSizeArray` object having same number of
/// elements as that of the specified `original`, the same value of
/// each element as that of corresponding element in `original`.
//! MyFixedSizeArray(const MyFixedSizeArray& original) = default;
/// Destroy this object.
//! ~MyFixedSizeArray() = default;
// MANIPULATORS
/// Return a bidirectional iterator providing modifiable access to
/// the first valid element of this object.
iterator begin();
/// Return a bidirectional iterator providing modifiable access to
/// the last valid element of this object.
iterator end();
/// Return a reference providing modifiable access to the element at
/// the specified `position`.
VALUE& operator[](int position);
// ACCESSORS
/// Return a bidirectional iterator providing non-modifiable access
/// to the first valid element of this object.
const_iterator begin() const;
/// Return a bidirectional iterator providing non-modifiable access
/// to the last valid element of this object.
const_iterator end() const;
/// Return a reference providing non-modifiable access to the
/// specified `i`th element in this object.
const VALUE& operator[](int position) const;
};

Then, we create a MyFixedSizeArray and initialize its elements:

MyFixedSizeArray<int, 5> fixedArray;
fixedArray[0] = 1;
fixedArray[1] = 2;
fixedArray[2] = 3;
fixedArray[3] = 4;
fixedArray[4] = 5;

Finally, to show that MyFixedSizeArray::iterator can be used as a bidirectional iterator, we invoke a function that takes bidirectional iterators as parameters, such as std::reverse, on the begin and end iterators and verify the results:

std::reverse(fixedArray.begin(), fixedArray.end());
assert(fixedArray[0] == 5);
assert(fixedArray[1] == 4);
assert(fixedArray[2] == 3);
assert(fixedArray[3] == 2);
assert(fixedArray[4] == 1);