[Patch] First bits of the algo merge

Howard Hinnant hhinnant@apple.com
Wed Dec 14 16:50:00 GMT 2005


On Dec 14, 2005, at 10:51 AM, Howard Hinnant wrote:

>  That proxy test is still on the way...

Ok, below is a test.  It isn't a testsuite test, though it could be  
made into one.  Rather it is a self contained HelloWorld that makes  
it easy to experiment.  It has both equal_to approaches, labeled by  
METHOD A and B.  #define METHOD to switch techniques.  A proxy  
iterator was quickly cobbled together from an earlier (unrelated)  
experiment.  And I looked for the simplest std::algorithm I could  
find which exercises this issue and chose equal.

#define A 0
#define B 1

#define METHOD A

#if METHOD == A

struct equal_to
{
     template <class _Lhs, class _Rhs>
     bool operator()(const _Lhs& __lhs, const _Lhs& __rhs) const  
{return __lhs == __rhs;}
};

#elif METHOD == B

template <class _Lhs, class _Rhs = _Lhs>
struct equal_to
{
     bool operator()(const _Lhs& __lhs, const _Lhs& __rhs) const  
{return __lhs == __rhs;}
     bool operator()(const _Lhs& __lhs, const _Rhs& __rhs) const  
{return __lhs == __rhs;}
     bool operator()(const _Rhs& __lhs, const _Lhs& __rhs) const  
{return __lhs == __rhs;}
     bool operator()(const _Rhs& __lhs, const _Rhs& __rhs) const  
{return __lhs == __rhs;}
};

template <class _Lhs>
struct equal_to<_Lhs, _Lhs>
{
     bool operator()(const _Lhs& __lhs, const _Lhs& __rhs) const  
{return __lhs == __rhs;}
};

#endif

#include <iterator>

template <class InputIterator1, class InputIterator2, class  
BinaryPredicate>
inline
bool
equal(InputIterator1 first1, InputIterator1 last1,
       InputIterator2 first2, BinaryPredicate pred)
{
     for (; first1 != last1; ++first1, ++first2)
         if (!pred(*first1, *first2))
             return false;
     return true;
}

template <class InputIterator1, class InputIterator2>
inline
bool
equal(InputIterator1 first1, InputIterator1 last1, InputIterator2  
first2)
{
     typedef typename  
std::iterator_traits<InputIterator1>::value_type value_type1;
     typedef typename  
std::iterator_traits<InputIterator2>::value_type value_type2;
#if METHOD == A
     return ::equal(first1, last1, first2, equal_to());
#elif METHOD == B
     return ::equal(first1, last1, first2, equal_to<value_type1,  
value_type2>());
#endif
}

#include <iostream>
#include <iterator>
#include <cstddef>

template <typename T>
class iterator
{
     class proxy
     {
         friend class iterator;
         iterator* const iter_;
         explicit proxy(iterator* iter) : iter_(iter) {}
     public:
         operator T& () const {return iter_->dirty_deref();}
         operator const T& () {return iter_->deref();}

         T* operator-> () const {return &iter_->dirty_deref();}
         const T* operator-> () {return &iter_->deref();}

         T& operator= (const T& rh) {return iter_->dirty_deref() = rh;}
     };

public:
     typedef T value_type;
     typedef std::ptrdiff_t difference_type;
     typedef proxy pointer;
     typedef proxy reference;
     typedef std::random_access_iterator_tag iterator_category;

private:
     T* ptr_;
     bool dirty_;

     T& dirty_deref() {dirty_ = true; return *ptr_;}
     const T& deref() {return *ptr_;}

public:
     iterator(T* v) : ptr_(v), dirty_(false) {}

     bool is_dirty() const  {return dirty_;}
     void reset_dirty() {dirty_ = false;}

     T* base() const {return ptr_;}

     proxy operator*() {return proxy(this);}
     proxy operator->() {return proxy(this);}
     const proxy operator->() const {return proxy 
(const_cast<iterator*>(this));}

     iterator& operator++() {++ptr_; return *this;}
     iterator operator++(int) {iterator tmp(*this); operator++();  
return tmp;}
     iterator& operator--() {--ptr_; return *this;}
     iterator operator--(int) {iterator tmp(*this); operator--();  
return tmp;}

     iterator& operator+=(difference_type n) {ptr_ += n; return *this;}
     iterator operator+(difference_type n) const {return iterator 
(*this) += n;}
     reference operator [] (difference_type i) const {return *(*this  
+ i);}

     iterator& operator-=(difference_type n) {return operator+=(-n);}
     iterator operator-(difference_type n) const {return iterator 
(*this) -= n;}
};

template <class T>
inline
iterator<T>
operator + (typename iterator<T>::difference_type n, const  
iterator<T>& y)
{
     return iterator<T>(y) += n;
}

template <class T>
inline
typename iterator<T>::difference_type
operator -(const iterator<T>& x, const iterator<T>& y)
{
     return x.base() - y.base();
}

template <class T>
inline
bool
operator ==(const iterator<T>& x, const iterator<T>& y)
{
     return x.base() == y.base();
}

template <class T>
inline
bool
operator !=(const iterator<T>& x, const iterator<T>& y)
{
     return !(x == y);
}

template <class T>
inline
bool
operator <(const iterator<T>& x, const iterator<T>& y)
{
     return x.base() < y.base();
}

template <class T>
inline
bool
operator >(const iterator<T>& x, const iterator<T>& y)
{
     return y < x;
}

template <class T>
inline
bool
operator <=(const iterator<T>& x, const iterator<T>& y)
{
     return !(y < x);
}

template <class T>
inline
bool
operator >=(const iterator<T>& x, const iterator<T>& y)
{
     return !(x < y);
}

int main()
{
     int array[] = {1, 2, 3};
     iterator<int> begin(array);
     iterator<int> end(array + sizeof(array)/sizeof(array[0]));
     std::cout << equal(begin, end, begin) << '\n';
}

With METHOD A I get:

main.cpp:42: error: no match for call to '(equal_to)  
(iterator<int>::proxy, iterator<int>::proxy)'

With METHOD B I get it to compile and print out:

1

Hope this helps.

-Howard



More information about the Libstdc++ mailing list