c++boost.gif (8819 bytes)

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

ParameterDescription
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...

0 1 2 3 

Template Parameters

ParameterDescription
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::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.