diff --git a/projection_iterator.htm b/projection_iterator.htm new file mode 100644 index 0000000..5e02e21 --- /dev/null +++ b/projection_iterator.htm @@ -0,0 +1,385 @@ + + + + + + +Projection Iterator Adaptor Documentation + + + + +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)  
+}
+
+ +
+ +

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
AdaptableUnaryFunctionThe 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. +
BaseIteratorThe 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
AdaptableUnaryFunctionThe 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. +
BaseIteratorThe mutable iterator type being wrapped.
ConstBaseIteratorThe 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_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 10 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.

+ + + + + + + + diff --git a/projection_iterator_example.cpp b/projection_iterator_example.cpp new file mode 100644 index 0000000..5405ced --- /dev/null +++ b/projection_iterator_example.cpp @@ -0,0 +1,96 @@ +// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +#include +#include +#include +#include +#include +#include +#include + +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_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::iterator>::type + personnel_first(personnel_list.begin()), + personnel_last(personnel_list.end()); + + std::copy(personnel_first, personnel_last, + std::ostream_iterator(std::cout, "\n")); + std::cout << std::endl; + + // Example of using projection_iterator_pair_generator + // to assign new ID numbers to the personnel. + + typedef boost::projection_iterator_pair_generator::iterator, + std::list::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(std::cout, " ")); + std::cout << std::endl; + std::cout << std::endl; + + // Example of using make_const_projection_iterator() + // to print out the names in the personnel list again. + + std::copy + (boost::make_const_projection_iterator(personnel_list.begin()), + boost::make_const_projection_iterator(personnel_list.end()), + std::ostream_iterator(std::cout, "\n")); + + return 0; +}