
[section:indirect Indirect Iterator]

`indirect_iterator` adapts an iterator by applying an
*extra* dereference inside of `operator*()`. For example, this
iterator adaptor makes it possible to view a container of pointers
(e.g. `list<foo*>`) as if it were a container of the pointed-to type
(e.g. `list<foo>`).  `indirect_iterator` depends on two
auxiliary traits, `pointee` and `indirect_reference`, to
provide support for underlying iterators whose `value_type` is
not an iterator.

[h2 Example]

This example prints an array of characters, using
`indirect_iterator` to access the array of characters through an
array of pointers. Next `indirect_iterator` is used with the
`transform` algorithm to copy the characters (incremented by one) to
another array. A constant indirect iterator is used for the source and
a mutable indirect iterator is used for the destination. The last part
of the example prints the original array of characters, but this time
using the `make_indirect_iterator` helper function.


    char characters[] = "abcdefg";
    const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char
    char* pointers_to_chars[N];                        // at the end.
    for (int i = 0; i < N; ++i)
      pointers_to_chars[i] = &characters[i];

    // Example of using indirect_iterator

    boost::indirect_iterator<char**, char>
      indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N);

    std::copy(indirect_first, indirect_last, std::ostream_iterator<char>(std::cout, ","));
    std::cout << std::endl;


    // Example of making mutable and constant indirect iterators

    char mutable_characters[N];
    char* pointers_to_mutable_chars[N];
    for (int j = 0; j < N; ++j)
      pointers_to_mutable_chars[j] = &mutable_characters[j];

    boost::indirect_iterator<char* const*> mutable_indirect_first(pointers_to_mutable_chars),
      mutable_indirect_last(pointers_to_mutable_chars + N);
    boost::indirect_iterator<char* const*, char const> const_indirect_first(pointers_to_chars),
      const_indirect_last(pointers_to_chars + N);

    std::transform(const_indirect_first, const_indirect_last,
		   mutable_indirect_first, std::bind1st(std::plus<char>(), 1));

    std::copy(mutable_indirect_first, mutable_indirect_last,
	      std::ostream_iterator<char>(std::cout, ","));
    std::cout << std::endl;


    // Example of using make_indirect_iterator()

    std::copy(boost::make_indirect_iterator(pointers_to_chars), 
	      boost::make_indirect_iterator(pointers_to_chars + N),
	      std::ostream_iterator<char>(std::cout, ","));
    std::cout << std::endl;


The output is:

    a,b,c,d,e,f,g,
    b,c,d,e,f,g,h,
    a,b,c,d,e,f,g,


The source code for this example can be found 
[@../example/indirect_iterator_example.cpp here].


[h2 Reference]

[h3 Synopsis]

  template <
      class Iterator
    , class Value = use_default
    , class CategoryOrTraversal = use_default
    , class Reference = use_default
    , class Difference = use_default
  >
  class indirect_iterator
  {
   public:
      typedef /* see below */ value_type;
      typedef /* see below */ reference;
      typedef /* see below */ pointer;
      typedef /* see below */ difference_type;
      typedef /* see below */ iterator_category;

      indirect_iterator();
      indirect_iterator(Iterator x);

      template <
          class Iterator2, class Value2, class Category2
        , class Reference2, class Difference2
      >
      indirect_iterator(
          indirect_iterator<
               Iterator2, Value2, Category2, Reference2, Difference2
          > const& y
        , typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition
      );

      Iterator const& base() const;
      reference operator*() const;
      indirect_iterator& operator++();
      indirect_iterator& operator--();
  private:
     Iterator m_iterator; // exposition
  };


The member types of `indirect_iterator` are defined according to
the following pseudo-code, where `V` is
`iterator_traits<Iterator>::value_type`

[pre
  if (Value is use_default) then
      typedef remove_const<pointee<V>::type>::type value_type;
  else
      typedef remove_const<Value>::type value_type;

  if (Reference is use_default) then
      if (Value is use_default) then
          typedef indirect_reference<V>::type reference;
      else
          typedef Value& reference;
  else
      typedef Reference reference;

  if (Value is use_default) then 
      typedef pointee<V>::type\* pointer;
  else 
      typedef Value\* pointer;

  if (Difference is use_default)
      typedef iterator_traits<Iterator>::difference_type difference_type;
  else
      typedef Difference difference_type;

  if (CategoryOrTraversal is use_default)
      typedef *iterator-category* (
          iterator_traversal<Iterator>::type,`reference`,`value_type`
      ) iterator_category;
  else
      typedef *iterator-category* (
          CategoryOrTraversal,`reference`,`value_type`
      ) iterator_category;
]


[h3 Requirements]

The expression `*v`, where `v` is an object of
`iterator_traits<Iterator>::value_type`, shall be valid
expression and convertible to `reference`.  `Iterator` shall
model the traversal concept indicated by `iterator_category`.
`Value`, `Reference`, and `Difference` shall be chosen so
that `value_type`, `reference`, and `difference_type` meet
the requirements indicated by `iterator_category`.

[blurb Note: there are further requirements on the
`iterator_traits<Iterator>::value_type` if the `Value`
parameter is not `use_default`, as implied by the algorithm for
deducing the default for the `value_type` member.]

[h3 Concepts]

In addition to the concepts indicated by `iterator_category`
and by `iterator_traversal<indirect_iterator>::type`, a
specialization of `indirect_iterator` models the following
concepts, Where `v` is an object of
`iterator_traits<Iterator>::value_type`:

Readable Iterator if `reference(*v)` is convertible to
`value_type`.

Writable Iterator if `reference(*v) = t` is a valid
expression (where `t` is an object of type
`indirect_iterator::value_type`)

Lvalue Iterator if `reference` is a reference type.

`indirect_iterator<X,V1,C1,R1,D1>` is interoperable with
`indirect_iterator<Y,V2,C2,R2,D2>` if and only if `X` is
interoperable with `Y`.

[h3 Operations]

In addition to the operations required by the concepts described
above, specializations of `indirect_iterator` provide the
following operations:


  indirect_iterator();

[*Requires: ] `Iterator` must be Default Constructible.\n
[*Effects: ] Constructs an instance of `indirect_iterator` with 
   a default-constructed `m_iterator`.


  indirect_iterator(Iterator x);

[*Effects: ] Constructs an instance of `indirect_iterator` with
    `m_iterator` copy constructed from `x`.


  template <
      class Iterator2, class Value2, unsigned Access, class Traversal
    , class Reference2, class Difference2
  >
  indirect_iterator(
      indirect_iterator<
           Iterator2, Value2, Access, Traversal, Reference2, Difference2
      > const& y
    , typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition
  );

[*Requires: ] `Iterator2` is implicitly convertible to `Iterator`.\n
[*Effects: ] Constructs an instance of `indirect_iterator` whose 
    `m_iterator` subobject is constructed from `y.base()`.


  Iterator const& base() const;

[*Returns: ] `m_iterator`


  reference operator*() const;

[*Returns: ] `**m_iterator`


  indirect_iterator& operator++();

[*Effects: ] `++m_iterator`\n
[*Returns: ] `*this`


  indirect_iterator& operator--();

[*Effects: ] `--m_iterator`\n
[*Returns: ] `*this`

[endsect]