# Projection Iterator Adaptor

Defined in header boost/iterator_adaptors.hpp

The projection iterator adaptor is similar to the transform iterator adaptor in that its `operator*()` applies some function to the result of dereferencing the base iterator and then returns the result. The difference is that the function must return a reference to some existing object (for example, a data member within the `value_type` of the base iterator). The following pseudo-code gives the basic idea. The data member `p` is the function object.

      reference projection_iterator::operator*() const {
        return this->p(*this->base_iterator);
      }

## Synopsis

    namespace boost {
      template <class AdaptableUnaryFunction, class BaseIterator>
      struct projection_iterator_generator;

      template <class AdaptableUnaryFunction,
                class BaseIterator, class ConstBaseIterator>
      struct projection_iterator_pair_generator;

      template <class AdaptableUnaryFunction, class BaseIterator>
      typename projection_iterator_generator<AdaptableUnaryFunction, BaseIterator>::type
      make_projection_iterator(BaseIterator base,
    			   const AdaptableUnaryFunction& p = AdaptableUnaryFunction())

      template <class AdaptableUnaryFunction, class ConstBaseIterator>
      typename projection_iterator_generator<AdaptableUnaryFunction, ConstBaseIterator>::type
      make_const_projection_iterator(ConstBaseIterator base,
                                     const AdaptableUnaryFunction& p = AdaptableUnaryFunction())
    }

## The Projection Iterator Type Generator

The class `projection_iterator_generator` is a helper class whose purpose is to construct an projection iterator type. The main template parameter for this class is the `AdaptableUnaryFunction` function object type and the `BaseIterator` type that is being wrapped.

    template <class AdaptableUnaryFunction, class BaseIterator>
    class projection_iterator_generator
    {
    public:
      typedef iterator_adaptor<...> type; // the resulting projection iterator type
    };

### Example

In the following example we have a list of personnel records. Each record has an employee's name and ID number. We want to be able to traverse through the list accessing either the name or the ID numbers of the employees using the projection iterator so we create the function object classes `select_name` and `select_ID`. We then use the `projection_iterator_generator` class to create a projection iterator and use it to print out the names of the employees.

    #include <boost/config.hpp>
    #include <list>
    #include <iostream>
    #include <iterator>
    #include <algorithm>
    #include <string>
    #include <boost/iterator_adaptors.hpp>

    struct personnel_record {
      personnel_record(std::string n, int id) : m_name(n), m_ID(id) { }
      std::string m_name;
      int m_ID;
    };

    struct select_name {
      typedef personnel_record argument_type;
      typedef std::string result_type;
      const std::string& operator()(const personnel_record& r) const {
        return r.m_name;
      }
      std::string& operator()(personnel_record& r) const {
        return r.m_name;
      }
    };

    struct select_ID {
      typedef personnel_record argument_type;
      typedef int result_type;
      const int& operator()(const personnel_record& r) const {
        return r.m_ID;
      }
      int& operator()(personnel_record& r) const {
        return r.m_ID;
      }
    };

    int main(int, char*[])
    {
      std::list<personnel_record> personnel_list;

      personnel_list.push_back(personnel_record("Barney", 13423));
      personnel_list.push_back(personnel_record("Fred", 12343));
      personnel_list.push_back(personnel_record("Wilma", 62454));
      personnel_list.push_back(personnel_record("Betty", 20490));

      // Example of using projection_iterator_generator
      // to print out the names in the personnel list.

      boost::projection_iterator_generator<select_name,
        std::list<personnel_record>::iterator>::type
        personnel_first(personnel_list.begin()),
        personnel_last(personnel_list.end());

      std::copy(personnel_first, personnel_last,
                std::ostream_iterator<std::string>(std::cout, "\n"));
      std::cout << std::endl;

      // to be continued...

The output for this part is:

    Barney
    Fred
    Wilma
    Betty

### Template Parameters

Parameter | Description
--- | ---
`AdaptableUnaryFunction` | The type of the function object. The `argument_type` of the function must match the value type of the base iterator. The function should return a reference to the function's `result_type`. The `result_type` will be the resulting iterator's `value_type`.
`BaseIterator` | The iterator type being wrapped.

### Model of

If the base iterator is a model of Random Access Iterator then so is the resulting projection iterator. If the base iterator supports less functionality than this the resulting projection iterator will also support less functionality.

### Members

The projection iterator type implements the member functions and operators required of the Random Access Iterator concept. In addition it has the following constructor:

    projection_iterator_generator::type(const BaseIterator& it,
                                        const AdaptableUnaryFunction& p = AdaptableUnaryFunction())

## The Projection Iterator Pair Generator

Sometimes a mutable/const pair of iterator types is needed, such as when implementing a container type. The `projection_iterator_pair_generator` class makes it more convenient to create this pair of iterator types.

    template <class AdaptableUnaryFunction, class BaseIterator, class ConstBaseIterator>
    class projection_iterator_pair_generator
    {
    public:
      typedef iterator_adaptor<...> iterator;       // the mutable projection iterator type
      typedef iterator_adaptor<...> const_iterator; // the immutable projection iterator type
    };

### Example

In this part of the example we use the `projection_iterator_pair_generator` to create a mutable/const pair of projection iterators that access the ID numbers of the personnel. We use the mutable iterator to re-index the ID numbers from zero. We then use the constant iterator to print the ID numbers out.

      // continuing from the last example...

      typedef boost::projection_iterator_pair_generator<select_ID,
        std::list<personnel_record>::iterator,
        std::list<personnel_record>::const_iterator> PairGen;

      PairGen::iterator ID_first(personnel_list.begin()),
        ID_last(personnel_list.end());

      int new_id = 0;
      while (ID_first != ID_last) {
        *ID_first = new_id++;
        ++ID_first;
      }

      PairGen::const_iterator const_ID_first(personnel_list.begin()),
        const_ID_last(personnel_list.end());

      std::copy(const_ID_first, const_ID_last,
                std::ostream_iterator<int>(std::cout, " "));
      std::cout << std::endl;
      std::cout << std::endl;

      // to be continued...
    </pre>
    The output is:
    <pre>
    0 1 2 3

### Template Parameters

Parameter | Description
--- | ---
`AdaptableUnaryFunction` | The type of the function object. The `argument_type` of the function must match the value type of the base iterator. The function should return a true reference to the function's `result_type`. The `result_type` will be the resulting iterator's `value_type`.
`BaseIterator` | The mutable iterator type being wrapped.
`ConstBaseIterator` | The constant iterator type being wrapped.

### Model of

If the base iterator types model the Random Access Iterator then so do the resulting projection iterator types. If the base iterators support less functionality the resulting projection iterator types will also support less functionality. The resulting `iterator` type is mutable, and the resulting `const_iterator` type is constant.

### Members

The resulting `iterator` and `const_iterator` types implements the member functions and operators required of the Random Access Iterator concept. In addition they support the following constructors:

    projection_iterator_pair_generator::iterator(const BaseIterator& it,
                                                 const AdaptableUnaryFunction& p = AdaptableUnaryFunction())

    projection_iterator_pair_generator::const_iterator(const BaseIterator& it,
                                                       const AdaptableUnaryFunction& p = AdaptableUnaryFunction())

## The Projection Iterator Object Generators

The `make_projection_iterator()` and `make_const_projection_iterator()` functions provide a more convenient way to create projection iterator objects. The functions save the user the trouble of explicitly writing out the iterator types.

    template <class AdaptableUnaryFunction, class BaseIterator>
    typename projection_iterator_generator<AdaptableUnaryFunction, BaseIterator>::type
    make_projection_iterator(BaseIterator base,
    			 const AdaptableUnaryFunction& p = AdaptableUnaryFunction())

    template <class AdaptableUnaryFunction, class ConstBaseIterator>
    typename projection_iterator_generator<AdaptableUnaryFunction, ConstBaseIterator>::type
    make_const_projection_iterator(ConstBaseIterator base,
    			       const AdaptableUnaryFunction& p = AdaptableUnaryFunction())

### Example

In this part of the example, we again print out the names of the personnel, but this time we use the `make_const_projection_iterator()` function to save some typing.

      // continuing from the last example...

      std::copy
        (boost::make_const_projection_iterator<select_name>(personnel_list.begin()),
         boost::make_const_projection_iterator<select_name>(personnel_list.end()),
         std::ostream_iterator<std::string>(std::cout, "\n"));

      return 0;
    }

The output is:

    Barney
    Fred
    Wilma
    Betty

Revised 28 Feb 2001

© Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.