#ifndef ARG_GRIN_PTR_H
#define ARG_GRIN_PTR_H
#ifndef ARG_COMPILER_H
#include "arg_compiler.h"
#endif
#ifndef ARG_DEEP_COPY_H
#include "arg_deep_copy.h"
#endif
#include ARG_STLHDR(iterator)
namespace arg
{
namespace iterator_body
{
template<typename value_type>
struct forward : cloneable
{
virtual ~forward() {}
virtual forward* clone() const = 0;
virtual value_type& operator*() const = 0;
virtual void increment() = 0;
virtual bool equals(const forward& rhs) const = 0;
};
template<typename value_type>
struct bidirectional
#ifndef ARG_COMPILER_NO_COVARIENT_RETURNS
: forward<value_type>
#else
: cloneable
#endif
{
virtual ~bidirectional() {}
virtual bidirectional* clone() const = 0;
virtual value_type& operator*() const = 0;
virtual void increment() = 0;
virtual void decrement() = 0;
virtual bool equals(const bidirectional& rhs) const = 0;
#ifndef ARG_COMPILER_NO_COVARIENT_RETURNS
virtual bool equals(const forward<value_type>& rhs) const
{ return equals(static_cast<const bidirectional&>(rhs)); }
#endif
};
}
template<typename value_type> class bidirectional_iterator;
template<typename value_type>
class forward_iterator : public std::forward_iterator_tag
{
public:
template<typename iterator>
forward_iterator(const iterator& it)
: body(new implementation<iterator>(it))
{
}
#ifdef _MSC_VER
// MSVC won't use the above template constructor with pointer types
forward_iterator(value_type* it)
: body(new implementation<value_type*>(it)) {}
#endif
/*
* Used to constructs a forward interator from a
* bidirectional_iterator.
*
* NB This conversion is not supportable on compilers (MSVC++) that
* disallow covarient return types. This simply leads to less
* efficient code - as the bidirectional_iterator gets wrapped up
* inside the forward_iterator.
*/
#ifndef ARG_COMPILER_NO_COVARIENT_RETURNS
forward_iterator(const bidirectional_iterator<value_type>& rhs)
: body(rhs.body->clone()) {}
#endif
value_type& operator*() const { return **body; }
value_type* operator->() const { return &**body; }
forward_iterator& operator++() { body->increment(); return *this; }
forward_iterator operator++(int)
{ forward_iterator r(*this); return ++r; }
bool equals(const forward_iterator& rhs) const
{ return body->equals(*rhs.body); }
private:
typedef iterator_body::forward<value_type> body_type;
body_part_ptr<body_type> body;
template<typename iterator>
struct implementation : body_type
{
implementation(iterator it) : i(it) {}
virtual ~implementation() {}
#ifndef ARG_COMPILER_NO_COVARIENT_RETURNS
virtual implementation* clone() const
#else
virtual body_type* clone() const
#endif
{ return new implementation(*this); }
virtual value_type& operator*() const { return *i; }
virtual void increment() { ++i; }
virtual bool equals(const body_type& rhs) const
{ return i == static_cast<const implementation&>(rhs).i; }
iterator i;
};
};
template<typename value_type>
inline bool operator==(
const forward_iterator<value_type>& lhs,
const forward_iterator<value_type>& rhs)
{
return lhs.equals(rhs);
}
template<typename value_type>
inline bool operator!=(
const forward_iterator<value_type>& lhs,
const forward_iterator<value_type>& rhs)
{
return !lhs.equals(rhs);
}
template<typename value_type>
class bidirectional_iterator : public std::bidirectional_iterator_tag
{
public:
template<typename iterator>
bidirectional_iterator(const iterator& it)
: body(new implementation<iterator>(it)) {}
#ifdef _MSC_VER
// MSVC can't use the above with pointer types
bidirectional_iterator(value_type* it)
: body(new implementation<value_type*>(it)) {}
#endif
value_type& operator*() const { return **body; }
value_type* operator->() const { return &**body; }
bidirectional_iterator& operator++()
{ body->increment(); return *this; }
bidirectional_iterator operator++(int)
{ bidirectional_iterator r(*this); return ++r; }
bidirectional_iterator& operator--()
{ body->decrement(); return *this; }
bidirectional_iterator operator--(int)
{ bidirectional_iterator r(*this); return --r; }
bool equals(const bidirectional_iterator& rhs) const
{ return body->equals(*rhs.body); }
private:
#ifndef ARG_COMPILER_NO_COVARIENT_RETURNS
friend forward_iterator<value_type>;
#endif
typedef iterator_body::bidirectional<value_type> body_type;
body_part_ptr<body_type> body;
template<typename iterator>
struct implementation : body_type
{
implementation(iterator it) : i(it) {}
virtual ~implementation() {}
#ifndef ARG_COMPILER_NO_COVARIENT_RETURNS
virtual implementation* clone() const
#else
virtual body_type* clone() const
#endif
{ return new implementation(*this); }
virtual value_type& operator*() const { return *i; }
virtual void increment() { ++i; }
virtual void decrement() { --i; }
virtual bool equals(const body_type& rhs) const
{ return i == static_cast<const implementation&>(rhs).i; }
iterator i;
};
};
template<typename value_type>
inline bool operator==(
const bidirectional_iterator<value_type>& lhs,
const bidirectional_iterator<value_type>& rhs)
{
return lhs.equals(rhs);
}
template<typename value_type>
inline bool operator!=(
const bidirectional_iterator<value_type>& lhs,
const bidirectional_iterator<value_type>& rhs)
{
return !lhs.equals(rhs);
}
}
#endif