#include <boost/config.hpp>
#include <boost/timer.hpp>
#include <iostream>

#if USE_BOOST_ITERATOR

#include <boost/iterator/iterator_facade.hpp>

template<typename Value>
class bidir_ptr_iterator:
  public boost::iterator_facade<
    bidir_ptr_iterator<Value>,
    Value,
    boost::bidirectional_traversal_tag>
{
public:
  bidir_ptr_iterator(){}
  explicit bidir_ptr_iterator(Value* ptr_):ptr(ptr_){}

protected:
  Value& dereference()const{return *ptr;}
  bool equal(const bidir_ptr_iterator& x)const{return ptr==x.ptr;}
  void increment(){++ptr;}
  void decrement(){--ptr;}

private:
  friend class boost::iterator_core_access;

  Value* ptr;
};

#else

# undef USE_BOOST_ITERATOR
# define USE_BOOST_ITERATOR 0

#include <boost/operators.hpp>

template<typename Value>
class bidir_ptr_iterator:
  public boost::bidirectional_iterator_helper<
    bidir_ptr_iterator<Value>,
    Value,
    std::ptrdiff_t,
    Value*,
    Value&>
{
public:
  bidir_ptr_iterator(){}
  explicit bidir_ptr_iterator(Value* ptr_):ptr(ptr_){}

  Value& operator*()const{return *ptr;}
  friend bool operator==(
    const bidir_ptr_iterator& x,const bidir_ptr_iterator& y)
  {return x.ptr==y.ptr;}
  bidir_ptr_iterator& operator++(){++ptr;return *this;}
  bidir_ptr_iterator& operator--(){--ptr;return *this;}

private:
  Value* ptr;
};

#endif

template<typename Value>
void use_iterator(BOOST_EXPLICIT_TEMPLATE_TYPE(Value))
{
  typedef bidir_ptr_iterator<Value> iterator;

  Value buf0[100];
  Value buf1[100];
  for(iterator it0(buf0),it0_end(buf0+100),it1(buf1);
      it0!=it0_end;
      ++it0,++it1){
    typename iterator::value_type v=*it0;
    *it1=v;
  }
}

#define INSTANTIATE_ITERATOR(Value)                                           \
{                                                                             \
  /* MSVC++ 6.0 needs this explicit instantiation for use_iterator to work */ \
  bidir_ptr_iterator<Value> it;                                               \
  use_iterator<Value>();                                                      \
}

int main()
{
    boost::timer time;
    for (int x = 0; x < 1000000; x++)
    {
  INSTANTIATE_ITERATOR(int)
  INSTANTIATE_ITERATOR(char)
  INSTANTIATE_ITERATOR(double)
  INSTANTIATE_ITERATOR(short)
  INSTANTIATE_ITERATOR(long)
  INSTANTIATE_ITERATOR(int*)
  INSTANTIATE_ITERATOR(char*)
  INSTANTIATE_ITERATOR(double*)
  INSTANTIATE_ITERATOR(short*)
  INSTANTIATE_ITERATOR(long*)
  INSTANTIATE_ITERATOR(int**)
  INSTANTIATE_ITERATOR(char**)
  INSTANTIATE_ITERATOR(double**)
  INSTANTIATE_ITERATOR(short**)
  INSTANTIATE_ITERATOR(long**)
      }
    double t = time.elapsed();
    std::cout << (USE_BOOST_ITERATOR ? "using iterator lib: " : "using operator lib: " ) << t << std::endl;
    
  return t < -1.0;
}


