[Patch] First bits of the algo merge

Howard Hinnant hhinnant@apple.com
Wed Dec 14 17:39:00 GMT 2005


On Dec 14, 2005, at 12:01 PM, Howard Hinnant wrote:

> I don't get it either.  I just noticed my bug too. Sorry for the  
> noise.  Back to work on the test...

Ok, I think I've got it this time.  I had forgotten how subtle the  
breakage was.  I originally stumbled over this only because of a use  
case with a proxy iterator in a far more complicated situation.   
Modified (and hopefully debugged) test case below.  The actual use  
case involved some implicit conversions (never a good thing) and I  
hope I've recreated enough of that context below.  In main I call  
equal two times:  Once with pointers, and once with the pointers  
wrapped in the proxy iterators.  METHOD A allows the former but not  
the latter.  METHOD B allows both.  Thanks in advance for your  
patience with this.

-Howard

#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 _Rhs& __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);
}

struct SmallNum {};

struct BigNum
{
     BigNum() {}
     BigNum(SmallNum) {}
};

bool operator==(const BigNum&, const BigNum&) {return true;}

int main()
{
     SmallNum s[3];
     BigNum   b[3];
     iterator<SmallNum> sb(s);
     iterator<SmallNum> se(s + 3);
     iterator<BigNum>   bb(b);
     std::cout << equal(s, s+3, b) << '\n';
     std::cout << equal(sb, se, bb) << '\n';
}



More information about the Libstdc++ mailing list