我正在尝试转换迭代器类,我必须与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);
}
答案 0 :(得分:11)
您正在将函数begin
和end
传递给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;
}