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);
}
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())
}
template <class AdaptableUnaryFunction, class BaseIterator>
class projection_iterator_generator
{
public:
typedef iterator_adaptor<...> type; // the resulting projection iterator type
};
#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
| 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. |
projection_iterator_generator::type(const BaseIterator& it,
const AdaptableUnaryFunction& p = AdaptableUnaryFunction())
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
};
// 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
| 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. |
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())
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())
// 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 19 Aug 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.