#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