1

this is a simple exercise. I'd like to write a custom iterator for a C-style array of characters all by myself: no boost. I think I'm halfway through, but I get an error when using std::count.

My iterator is this:

class myIterator : std::iterator<std::input_iterator_tag, char>
{
    char *p;

public:

    // Definitions
    typedef typename std::iterator<std::input_iterator_tag, char>::difference_type difference_type;
    typedef typename std::iterator<std::input_iterator_tag, char>::value_type value_type;
    typedef typename std::iterator<std::input_iterator_tag, char>::reference reference;
    typedef typename std::iterator<std::input_iterator_tag, char>::pointer pointer;

    // Implementation
    myIterator(char* x) :p(x) { };
    myIterator(const myIterator& i) : p(i.p) { };
    myIterator& operator++() { ++p; return *this; };
    myIterator operator++(int) {myIterator tmp(*this); operator++(); return tmp; };
    bool operator==(const myIterator& rhs) { return p == rhs.p; };
    bool operator!=(const myIterator& rhs) { return p != rhs.p; };
    char& operator*() { return *p; };
};

So, when I use the iterator in a for loop, it's great, it

for (auto it = data.begin(); it != data.end(); it++)
   std::cout << *it;

However, this gets a compile-time error:

std::cout << std::count(data.begin(), data.end(), '@') << std::endl;

For what it's worth, data is a super-simple class with a classic wrapping function for begin() and end() (i.e., return myIterator(address_); and return myIterator(address_ + size_);).

What's the error is puzzling to me:

error: no matching function for call to 'count'
[...]
note: candidate template ignored: substitution failure [with _InputIterator = myIterator, _Tp = char]: no type named 'difference_type' in 'std::__1::iterator_traits<myIterator>'
count(_InputIterator __first, _InputIterator __last, const _Tp& __value_)

I am missing something here: I declared difference_type in the iterator.

Can anyone help?

4

2 回答 2

5

std::iterator从已经定义value_type的 ,等派生你的类difference_type。所以你不应该定义它们。只需公开您的继承并删除那些typedefs 即可:

class myIterator : public std::iterator<std::input_iterator_tag, char>
{
    char *p;

public:
    // Implementation
    myIterator(char* x) :p(x) { };
    // ......
};

请注意,没有必要删除typedefs,但没有理由手动定义它们,std::iterator已经这样做了。

演示在这里

于 2013-10-16T13:27:50.133 回答
2

我不确定这是否是问题,但通常的使用方式 std::iterator是从它公开继承。或者不使用它,并定义它的所有五个typedef。我猜您的代码不起作用的原因是 typedef foriterator_category 不可访问:如果您不公开派生自 std::iterator,则必须提供它。

对于它的价值,有三种方法可以使迭代器类型符合:从 公开继承,直接在你的类中声明std::iterator五个类型定义(value_typedifference_type, 和类型定义)。第一个是迄今为止最简单和最常见的。pointerreferenceiterator_categorystd::iterator_traits

于 2013-10-16T13:29:32.927 回答