0

I am implementing an iterator for a custom container in c++11

I get the following error:

no type named 'value_type' in 'struct std::iterator_traits<PixBuffer<float>::seq_read_iterator>'
    typedef typename iterator_traits<_OI>::value_type _ValueTypeO;

I have read before the answer here: How to implement an STL-style iterator and avoid common pitfalls?

It states that I can:

  • specialize std::iterator_traits<youriterator> : This is not the preferred method according to the author, for code readability, as this type declaration is not nested in the class
  • Put the same typedefs in the iterator itself : I did this but I still have the error above
  • Inherit from std::iterator : will this fix my problem, and what is the proper way to use this method?

This interator works as a back_inserter. The current class definition is:

template<typename T>
class PixBuffer
{
public:
    friend class seq_read_iterator;

    /* container class implementation removed from here */

public:
    class seq_read_iterator
    {
    public:
        typedef T value_type;

        seq_read_iterator(PixBuffer & pb);
        seq_read_iterator & operator*(T val);
        seq_read_iterator & operator++();
        seq_read_iterator operator++(int);
        seq_read_iterator & operator=(T val);

        /* iterator class implementation removed from here */
    };


    seq_read_iterator seqReadIterator() { return seq_read_iterator(*this); }
};

Thanks in advance

Community
  • 1
  • 1
galinette
  • 8,896
  • 2
  • 36
  • 87
  • 3
    "_Put the same typedefs in the iterator itself : I did this but I still have the error above_". It seems like you did it wrongly. Show relevant parts an maybe we could help. – Revolver_Ocelot Jan 22 '16 at 10:21
  • 1
    Regarding "I thought this was forbidden by the standard": `[namespace.std]/1` "A program may add a template specialization for any standard library template to namespace `std` only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited." – TartanLlama Jan 22 '16 at 10:23
  • @Revolver_Ocelot : Code added – galinette Jan 22 '16 at 10:26
  • @TartanLlama : you are right, this is valid. I would prefer another method for better code organization, though, if possible. – galinette Jan 22 '16 at 10:27
  • The current trend seems to be option 2, add the typedefs to the iterator. That's what the standard document does in later drafts. – Bo Persson Jan 22 '16 at 10:35
  • related http://stackoverflow.com/q/29108958/819272 – TemplateRex Jan 22 '16 at 11:10

1 Answers1

2

All 3 posted ways to make iterator work are legal.

Preferred way is to add required type aliases to the class itself. Inheriting from std::iterator is just a quick way to do that.

Specializing std::iterator_traits is usually used, when you already have a non-conforming iterator, which code you cannot change.


Your code does not work because you did not add all 5 required type aliases. Before C++11 it would just explode and complain that it cannot instantiate iterator_traits. Now it just creates empty trait class:

http://en.cppreference.com/w/cpp/iterator/iterator_traits

If Iterator does not have the five member types difference_type, value_type, pointer, reference, and iterator_category, then this template has no member types (std::iterator_traits is SFINAE-friendly)

Revolver_Ocelot
  • 8,609
  • 3
  • 30
  • 48