编写stl兼容的迭代器

时间:2010-07-06 00:28:41

标签: c++ stl iterator

我正在尝试转换迭代器类,我必须与stl兼容,以便它可以与stl算法一起使用。在下面的简单(和坦率无用)示例中,应该打印0到5的值,我收到以下错误,

ISO C ++禁止递增“Iterator(*)()'

类型的指针

从'Iterator(*)()'到'int'的无效转换

我做错了什么?

感谢。


#include <iterator>
#include <algorithm>
#include <iostream>

class Iterator : public std::iterator<std::bidirectional_iterator_tag, int> {
    public:
        Iterator(int i = 0) : val(i) {
            if(val<0 || val>5) throw;
        }

        bool operator==(Iterator const& rhs) const {
            return (val==rhs.val);
        }

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

        Iterator& operator++() {
            if(val!=6)
                ++val;
            return *this;
        }   

        Iterator operator++(int) {
            Iterator tmp (*this);
            ++(*this);
            return tmp;
        }

        Iterator& operator--() {
            if(val!=-1)
                --val;
            return *this;
        }

        Iterator operator--(int) {
            Iterator tmp (*this);
            --(*this);
            return tmp;
        }

        int operator* () const {
            if(val==-1 || val==6) throw;
            return val;
        }

    private:
        int val;
};

Iterator begin() {
    return Iterator();
}

Iterator end() {
    return ++Iterator(5);
}

void print(int i) {
    std::cout << i << std::endl;
}

int main(int argc, char* argv[]) {
    std::for_each(begin,end,print);
}

2 个答案:

答案 0 :(得分:11)

您正在将函数beginend传递给std::for_each,而不是这些函数将返回的迭代器:

std::for_each(begin,end,print);

应该是:

std::for_each(begin(),end(),print);

另请注意,throw中的空if(val==-1 || val==6) throw;语句不会有任何好处。您投掷某些内容,例如throw std::out_of_range("out of bounds")

答案 1 :(得分:9)

首先,您应该传递由begin()和end()返回的迭代器而不是函数本身:

int main(int argc, char* argv[]) 
{
    std::for_each(begin(),end(),print);
}

其次,有一个模板化的Iterator类是有用的:

template<class T>
class Iterator : public std::iterator<std::bidirectional_iterator_tag, int>
{
    public:
        typedef T value_type; //notice this here :D

        Iterator(value_type t = 0) : val(t) 
        {
            if(val<0 || val>5) throw; //never hardcode something like that :S
        }

        bool operator==(Iterator const& rhs) const 
        {
            return (val==rhs.val);
        }

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

        Iterator& operator++() 
        {
            if(val!=6) //never hardcode something like that :S
                ++val;
            return *this;
        }   

        Iterator operator++(value_type) 
        {
            Iterator tmp (*this);
            ++(*this);
            return tmp;
        }

        Iterator& operator--() 
        {
            if(val!=-1) //never hardcode something like that :S
                --val;
            return *this;
        }

        Iterator operator--(value_type) 
        {
            Iterator tmp (*this);
            --(*this);
            return tmp;
        }

        value_type operator* () const 
        {
            if(val==-1 || val==6) throw; //never hardcode something like that :S
            return val;
        }

    private:
        value_type val;
};

第三,你可能真的不想像这样拥有一个迭代器类。这是你可以做的一个例子(注意迭代器类有点低):

#include <algorithm>

template<class T>
class List
{
public:
    typedef T value_type;
    typedef std::size_t size_type;

private:
    struct Knot
    {
        value_type val_;
        Knot * next_;
        Knot(const value_type &val)
        :val_(val), next_(0)
        {}
    };
    Knot * head_;
    size_type nelems_;

public:
    //Default constructor
    List() throw()
    :head_(0), nelems_(0)
    {}
    bool empty() const throw()
    { return size() == 0; }
    size_type size() const throw()
    { return nelems_; }

private:
    Knot * last() throw() //could be done better
    {
        if(empty()) return 0;
        Knot *p = head_;
        while (p->next_)
            p = p->next_;
        return p;
    }

public:
    void push_back(const value_type & val)
    {
        Knot *p = last();
        if(!p)
            head_ = new Knot(val);
        else
            p->next_ = new Knot(val);
        ++nelems_;
    }
    void clear() throw()
    {
        while(head_)
        {
            Knot *p = head_->next_;
            delete head_;
            head_ = p;
        }
        nelems_ = 0;
    }
    //Destructor:
    ~List() throw()
    { clear(); }
    //Iterators:
    class iterator
    {
        Knot * cur_;
    public:
        iterator(Knot *p) throw()
        :cur_(p)
        {}
        bool operator==(const iterator & iter)const throw()
        { return cur_ == iter.cur_; }
        bool operator!=(const iterator & iter)const throw()
        { return !(*this == iter); }
        iterator & operator++()
        {
            cur_ = cur_->next_;
            return *this;
        }
        iterator operator++(int)
        {
            iterator temp(*this);
            operator++();
            return temp;
        }
        value_type & operator*()throw()
        { return cur_->val_; }
        value_type operator*() const
        { return cur_->val_; }
        value_type operator->()
        { return cur_->val_; }
        const value_type operator->() const
        { return cur_->val_; }
    };
    iterator begin() throw()
    { return iterator(head_); }
    iterator begin() const throw()
    { return iterator(head_); }
    iterator end() throw()
    { return iterator(0); }
    iterator end() const throw()
    { return iterator(0); }
    //Copy constructor:
    List(const List & lst)
    :head_(0), nelems_(0)
    {
        for(iterator i = lst.begin(); i != lst.end(); ++i)
            push_back(*i);
    }
    void swap(List & lst) throw()
    {
        std::swap(head_, lst.head_);
        std::swap(nelems_, lst.nelems_);
    }
    List & operator=(const List & lst)
    {
        List(lst).swap(*this);
        return *this;
    }
    //Conversion constructor
    template<class U>
    List(const List<U> &lst)
    :head_(0), nelems_(0)
    {
        for(typename List<U>::iterator iter = lst.begin(); iter != lst.end(); ++iter)
            push_back(*iter);
    }
    template<class U>
    List & operator=(const List<U> &lst)
    {
        List(lst).swap(*this);
        return *this;
    }
    //Sequence constructor:
    template<class Iter>
    List(Iter first, Iter last)
    :head_(0), nelems_(0)
    {
        for(;first!=last; ++first)
            push_back(*first);
    }
};

#include <iostream>
using std::cout;
using std::endl;

int main()
{
    const char MAX_LIMIT = 127;
    List<short> listA;
    //...
    List<char> listB = listA; //without the conversion constructor this would not go very far!
    for(char i = 0; i < MAX_LIMIT; ++i)
        listB.push_back(i);
    for(List<char>::iterator iter = listB.begin(); iter != lstB.end(); ++iter)
        cout << *iter << endl;
}