Search code examples
c++iteratorstd

find() does not recognize my custom iterator


I wrote a custom iterator named Text_Iterator for a simple text editor. However, STL algorithms such as find() would not recognize it as a legitimate iterator.

My code is:

using Line = std::vector<char>;

class Text_iterator {
    std::list<Line>::iterator ln;
    Line::iterator pos;

public:
    Text_iterator(std::list<Line>::iterator ll, Line::iterator pp)
        : ln{ll}, pos{pp} {}

    char& operator*() { return *pos; }
    Text_iterator& operator++();
    Text_iterator& operator--();

    bool operator==(const Text_iterator& other) const 
    {
        return (ln == other.ln && pos == other.pos);
    }
    bool operator!=(const Text_iterator& other) const
    {
        return (!(*this == other));
    }
};

When I try to use this iterator in an algorithm, for example in find(), I get the following error:

1>...\xutility(861,56): error C2794: 'value_type': is not a member of any direct or indirect base class of 'std::iterator_traits<_InIt>'
1>        with
1>        [
1>            _InIt=Text_iterator
1>        ]

Why would it not register as a legitimate iterator?

Edit: Works with the following additional declarations:

using iterator_category = std::bidirectional_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = char;
using pointer = char*;
using reference = char&;

Solution

  • The error message is complaining that std::iterator_traits does not have a value_type member when applied to your Text_iterator class.

    Your class's operator* is returning a char&, but your class does not have a value_type member that aliases char, eg:

    class Text_iterator {
        ...
    
    public:
        typedef char value_type;
        // or: using value_type = char;
        // or: typedef std::iterator_traits<Line::iterator>::value_type value_type;
        // or: using value_type = st::iterator_traits<Line::iterator>::value_type;
        ...
    };
    

    std::find() only works with iterators that satisfy the requirements of InputIterator or ForwardIterator.

    So, you need to either

    • add the required members to your class (there are several more than just value_type) so the default std::iterator_traits can find them.
    • specialize std::iterator_traits for your class.