This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [Patch] First bits of the algo merge


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]