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: Iterators wrappers?


Chris Jefferson wrote:
Hello,

I am currently working on some test cases for some functions in the algorithm header. I wondered if there exists any "exact iterator checkers",

Here's an input iterator I've used to test our algorithms. It lets you wrap an ordinary pointer (not another iterator) into a sequence of elements. We don't use container iterators (or any other parts of the library) when testing algorithms to prevent bugs in those areas from causing false negatives (or positives) in the tests.

Martin
template <class T>
struct InputIter
{
    typedef T                       value_type;
    typedef value_type*             pointer;
    typedef value_type&             reference;
    typedef std::ptrdiff_t          difference_type;
    typedef std::input_iterator_tag iterator_category;

    // body shared by all copies of the same InputIter specialization
    // to detect algorithms that pass through the same interator more
    // than once (disallowed by 24.1.1, p3)
    struct Shared {
        const value_type *cur_;
        const value_type *end_;
        int               ref_;

        Shared (const value_type *cur, const value_type *end)
            : cur_ (cur), end_ (end), ref_ (1) { }

        ~Shared () {
            end_ = cur_ = 0;
            ref_ = -1;
        }

    private:
        Shared (const Shared&);           // not defined
        void operator= (const Shared&);   // not defined

    };

    // not default constructible
    InputIter (const value_type *cur, const value_type *end)
        : ptr_ (new Shared (cur, end)), cur_ (cur) { }

    InputIter (const InputIter &rhs)
        : ptr_ (rhs.ptr_), cur_ (rhs.cur_) {
        ++ptr_->ref_;
    }

    ~InputIter () {
        if (0 == --ptr_->ref_)   // decrement the reference count
            delete ptr_;
        ptr_ = 0;
        cur_ = 0;
    }

    InputIter& operator= (const InputIter &rhs) {
        if (0 == --ptr_->ref_)
            delete ptr_;

        ptr_ = rhs.ptr_;
        ++ptr_->ref_;

        cur_ = rhs.cur_;

        return *this;
    }

    bool operator== (const InputIter &rhs) const {
        return cur_ == rhs.cur_;
    }

    bool operator!= (const InputIter &rhs) const {
        return !(*this == rhs);
    }

    // returning const-reference rather than a value in order
    // not to impose the CopyConstructible requirement on T
    // and to disallow constructs like *InputIter<T>() = T()
    const value_type& operator* () const {
        assert (cur_ && ptr_ && cur_ != ptr_->end_);
        return *cur_;
    }

    const value_type* operator-> () const {
        return &**this;
    }

    InputIter& operator++ () {
        assert (ptr_ && ptr_->cur_ && ptr_->cur_ != ptr_->end_);

        // verify that another copy of this iterator hasn't
        // passed through this value yet
        assert (ptr_->cur_ == cur_);

        ptr_->cur_ = ++cur_;

        return *this;
    }

    InputIter operator++ (int) {
        return ++*this;
    }

private:
    Shared           *ptr_;
    const value_type *cur_;   // past-the-end
};


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