Boost logo

Boost :

From: Dave Abrahams (abrahams_at_[hidden])
Date: 1999-11-29 07:33:54


Jeremy wrote:

> Here's the current version of iterator_ops.hpp, so if you all want to
> you can add it to operators.hpp.

I only wanted to add incrementable, decrementable, and dereferenceable
(possibly indexable, though that is rather iterator-specific, e.g. it
doesn't handle indexing for things like vector).

I propose the following improvements/compiler bug workarounds. I'd like a
better alternative to the way difference_type_mismatch works right now.

-D
-------------

// (C) Copyright Jeremy Siek 1999. 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.

#ifndef BOOST_ITERATOR_OPS_HPP
#define BOOST_ITERATOR_OPS_HPP

#include <iterator>
#include <boost/operators.hpp>

#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
namespace boost
{
#endif

template <class T>
struct incrementable
{
  friend T operator++(T& x, int)
  {
    T tmp(x);
    ++x;
    return tmp;
  }
};

template <class T>
struct decrementable
{
  friend T operator--(T& x, int)
  {
    T tmp(x);
    --x;
    return tmp;
  }
};

template <class T, class V>
struct dereferenceable
{
  V* operator->() const
  {
    return &*static_cast<const T&>(*this);
  }
};

template <class T, class D, class R>
struct indexable
{
  R operator[](D n) const
  {
    return *(static_cast<const T&>(*this) + n);
  }
};

template <class T,
          class V,
          class D = std::iterator_traits<char*>::difference_type,
          class P = V*,
          class R = V&>
struct forward_iterator_helper :
  equality_comparable<T,T>,
  incrementable<T>,
  dereferenceable<T,V>,
  std::iterator<std::forward_iterator_tag, V, D, P, R> { };

template <class T,
          class V,
          class D = std::iterator_traits<char*>::difference_type,
          class P = V*,
          class R = V&>
struct bidirectional_iterator_helper :
  equality_comparable<T,T>,
  incrementable<T>,
  decrementable<T>,
  dereferenceable<T,V>,
  std::iterator<std::bidirectional_iterator_tag, V, D, P, R> { };

template <class D>
struct difference_type_mismatch
{
 difference_type_mismatch(const D&);
 
 template <class X>
 difference_type_mismatch(const X& x) { return
x->this_member_probably_does_not_exist; }
};

template <class T,
          class V,
          class D = std::iterator_traits<char*>::difference_type,
          class P = V*,
          class R = V&>
struct random_access_iterator_helper :
  equality_comparable<T,T>,
  less_than_comparable<T,T>,
  incrementable<T>,
  decrementable<T>,
  dereferenceable<T,V>,
  addable<T,D>,
  subtractable<T,D>,
  indexable<T,D,R>,
  std::iterator<std::random_access_iterator_tag, V, D, P, R>
{
  friend void requires_difference_operator(const T& x, const T& y) {
    difference_type_mismatch<D>(x - y);
  }
};

#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
} /* namespace boost */
#else

namespace boost {
  using ::incrementable;
  using ::decrementable;
  using ::dereferenceable;
  using ::indexable;
  using ::forward_iterator_helper;
  using ::bidirectional_iterator_helper;
  using ::random_access_iterator_helper;
}

#endif

#endif /* BOOST_ITERATOR_OPS_HPP */

// (C) Copyright Jeremy Siek 1999. 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 <string>
#include <iostream>
#include <iterator>
#include <boost/array.hpp>
#include <mtl/iterator_ops.hpp>

using namespace std;
using namespace boost;

template <class T>
struct test_iter
  : public boost::random_access_iterator_helper<test_iter<T>, T>
{
  typedef test_iter self;
#if !defined(__MWERKS__) || __MWERKS__ > 0x2301
  typedef typename self::reference Reference;
  typedef typename self::difference_type Distance;
#else
  typedef T& Reference;
  typedef typename std::iterator_traits<char*>::difference_type Distance;
#endif
public:
  test_iter(T* i) : _i(i) { }
  test_iter(const self& x) : _i(x._i) { }
  self& operator=(const self& x) { _i = x._i; return *this; }
  Reference operator*() const { return *_i; }
  self& operator++() { ++_i; return *this; }
  self& operator--() { --_i; return *this; }
  self& operator+=(Distance n) { _i += n; return *this; }
  self& operator-=(Distance n) { _i -= n; return *this; }
  friend bool operator==(const self& x, const self& y) { return x._i ==
y._i; }
  friend bool operator<(const self& x, const self& y) { return x._i < y._i;
}
  friend Distance operator-(const self& x, const self& y) {
    return x._i - y._i; }
protected:
  T* _i;
};

int
main()
{
  string array[] = { "apple", "orange", "pear", "peach", "grape", "plum" };
#if !defined(__MWERKS__) || __MWERKS__ > 0x2301
  const test_iter<string> ic = begin(array), iec = end(array);
  const std::size_t sz = size(array);
#else
  const std::size_t sz = sizeof(array)/sizeof(*array);
  const test_iter<string> ic = array, iec = array + sz;
#endif
  test_iter<string> i = ic, ie = iec;

  // Tests for all of the operators added by random_access_iterator_helper

  // test i++
  while (i != ie)
    cout << *i++ << " ";
  cout << endl;
  i = ic;

  // test i--
  while (ie != i) {
    ie--;
    cout << *ie << " ";
  }
  cout << endl;
  ie = iec;

  // test i->m
  while (i != ie) {
    cout << i->size() << " ";
    ++i;
  }
  cout << endl;
  i = ic;

  // test i + n
  while (i < ie) {
    cout << *i << " ";
    i = i + 2;
  }
  cout << endl;
  i = ic;

  // test n + i
  while (i < ie) {
    cout << *i << " ";
    i = 2 + i;
  }
  cout << endl;
  i = ic;

  // test i - n
  while (ie > i) {
    ie = ie - 2;
    cout << *ie << " ";
  }
  cout << endl;
  ie = iec;

  // test i[n]
  for (int j = 0; j < sz; ++j)
    cout << i[j] << " ";
  cout << endl;

  return 0;
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk