CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11

Thread: custom iterator

  1. #1
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    custom iterator

    I have a class which holds some objects.
    To be more specific the class MyClass has an array of 9 "Obj". like this:

    Code:
    #include"Obj.h"
    
    class MyClass
    {
        Obj _objects[9];
    }
    I would like to be able to access these objects with an iterator style object. Since my objects can be accessed with a standard pointer, I shouldn't need to implement the entire iterator class, but just declare a typedef. I am not sure how to do it though.

    http://www.cplusplus.com/reference/s...erator_traits/
    According to this, I would try to create a class that inherits from iterator_traits<Obj>, but at the same time, a want to write "typedef Obj* iterator"

    How should I do this?

  2. #2
    Join Date
    Jan 2006
    Location
    Belo Horizonte, Brazil
    Posts
    405

    Re: custom iterator

    Apparently, you're talking about two related but different things.

    Providing access to your internal array through an iterator style is simple. What I usually do is to return a pair with the begin and end iterators. Since you're using a C array your iterators are raw pointers. That's is fine because raw pointers model the STL iterators concepts.
    (I just suggest you to take a look at std::vector or boost::array).

    Code:
    #include <utility>
    #include <iostream>
    
    typedef int Obj;
    
    class MyClass
    {
    public:
      typedef Obj const* const_iterator;
      
      std::pair<const_iterator, const_iterator> get_objects() const
      { return std::make_pair(objects_, objects_ + 9); }  
      
    private:
        Obj objects_[9]; //I preffer using a trailling underscore. Leading underscores are reserved in several cases.
    };
    
    int main()
    {
      MyClass m;
      
      typedef MyClass::const_iterator const_iterator;
      std::pair<const_iterator, const_iterator> ci = m.get_objects();
      for (; ci.first != ci.second; ++ci.first)
        std::cout << *(ci.first) << " ";
      std::cout << std::endl;
      
      return 0;
    }
    Another situation is when you create you own container and want to have interoperability with STL algorithms. In this case, you need to implement the iterator classes (or define them somehow) in accordance to some rules. Basically, there are two approaches: Make your iterator classes define the types expected by std::iterator_traits or specialize std::iterator_traits for your iterator classes (notice that you don't inherit from std::iterator_traits, you specialize it). I prefer the first option.

    Does that help you?

  3. #3
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: custom iterator

    Quote Originally Posted by ltcmelo View Post
    Apparently, you're talking about two related but different things.

    Another situation is when you create you own container and want to have interoperability with STL algorithms. In this case, you need to implement the iterator classes (or define them somehow) in accordance to some rules. Basically, there are two approaches: Make your iterator classes define the types expected by std::iterator_traits or specialize std::iterator_traits for your iterator classes (notice that you don't inherit from std::iterator_traits, you specialize it). I prefer the first option.

    Does that help you?
    I have a questions:
    Are pointers compatible with all stl algorithms?


    I will also need to create an iterator class for another class of mine. For reasons I will not dwell upon, it needs a random access iterator that returns only the even elements of my array.

    so it++ will actually increment the internal pointer by two, or it+=4 will increment the internal pointer by four.

    according to http://www.cplusplus.com/reference/s...erator_traits/ , since my iterator is a pointer type, I shouldn't need to redefine all those types. I just have to redefine the operators.

    will this work, or how should it be done?

    Code:
    class iterator : public std::iterator_traits<obj>
    {
    public:
        iterator& operator++();
        etc...
    private:
        obj* _internalPointer;
    }
    Thanks for your help.

  4. #4
    Join Date
    Jan 2006
    Location
    Belo Horizonte, Brazil
    Posts
    405

    Re: custom iterator

    Quote Originally Posted by monarch_dodra View Post
    Are pointers compatible with all stl algorithms?
    The most powerfull iterator concept is Random Access Iterator. It refines Bidirectional Iterator, which then refines Forward Iterator, and this goes on...
    If you take a look here you'll notice that raw pointers are models of Random Access Iterators. So you can assume they work with all STL algorithms.

    Quote Originally Posted by monarch_dodra View Post
    will this work, or how should it be done?

    Code:
    class iterator : public std::iterator_traits<obj>
    {
    public:
        iterator& operator++();
        etc...
    private:
        obj* _internalPointer;
    }
    No. As I mentioned you don't inherit from std::iterator_traits. It doesn't work this way. I'll try to explain again.

    When writing your very_peculiar_iterator class you have two options. The first (which is usually the best when you control the implementation of the iterator class) is to place nested types inside it (using typedefs) for everything that is expected by std::iterator_traits. In this approach, std::iterator_traits is naturally instantiated with your type. For example:

    Code:
    class very_peculiar_iterator
    {
    public:
      typedef something value_type;
      typedef something* pointer;
      //Other required types...
     
    private:
      //Implementation...  
    };
    The other option (which you should use when you can't manipulate the iterator class source code) is to specialize std::iterator_traits for your very_peculiar_iterator class. This way, when the std::iterator_traits template gets instantiated it will use the explicit specialization you provided. For example:

    Code:
    class very_peculiar_iterator
    {
    private:
      //Implementation...  
    };
    
    template <>
    struct iterator_traits<very_peculiar_iterator>
    {
      typedef typename very_peculiar_iterator::something value_type;
      typedef typename very_peculiar_iterator::something* pointer;
      //Other required types...
    };
    I hope I cleared some of your doubts. If you're still a bit confused, perhaps you would like to read about C++ template specialization and what traits classes are for.

  5. #5
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: custom iterator

    Quote Originally Posted by ltcmelo View Post
    I hope I cleared some of your doubts. If you're still a bit confused, perhaps you would like to read about C++ template specialization and what traits classes are for.
    Not confused. I am quite confident on USING iterators, and I fully understand the differences in types of iterators, and that a pointer is a random access iterator by excellence. I've used traits a few times before, so it's not new

    I just wasn't sure how to implement an iterator and/or traits, or if a pointer can be used in any algorithm. After all, std:istance, for example, uses iterator traits to choose how to work. pointers don't define iterator traits typedefs, so I thought that might pose a problem.

    I understand you can re-define all the typdefs yourself, or just do a total template specialisation for your iterator.

    But why can't you inherit? After all, isn't that how you implement a binary function, you inherit from binary_function<T,U>, you don't redefine the typedefs manually?

    Thank you very much for your input. It helps a lot. I don't want to make it look like I don't agree or apreciate your help.
    I'm just the kind of person who likes to understand how things work. I want more than the solution

  6. #6
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: custom iterator

    Quote Originally Posted by monarch_dodra View Post
    But why can't you inherit? After all, isn't that how you implement a binary function, you inherit from binary_function<T,U>, you don't redefine the typedefs manually?
    You can with the boost iterator library.
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  7. #7
    Join Date
    Jan 2006
    Location
    Belo Horizonte, Brazil
    Posts
    405

    Re: custom iterator

    Quote Originally Posted by D_Drmmr View Post
    If I recall correctly, there's no class in the boost iterator library that inherits from std::iterator_traits. What exactly do you mean?

  8. #8
    Join Date
    Jan 2006
    Location
    Belo Horizonte, Brazil
    Posts
    405

    Re: custom iterator

    Quote Originally Posted by monarch_dodra View Post
    I fully understand the differences in types of iterators, and that a pointer is a random access iterator by excellence...
    I just wasn't sure how to implement an iterator and/or traits, or if a pointer can be used in any algorithm.
    I get it. But notice that if you know a pointer is a random access iterator, you're question is actually if random access iterators can be used in any algorithm.

    Quote Originally Posted by monarch_dodra View Post
    After all, std:istance, for example, uses iterator traits to choose how to work. pointers don't define iterator traits typedefs, so I thought that might pose a problem.
    Pointer don't need to define typedes because std::iterator_traits already provides an specialization for pointer types. In fact, that link you mentioned on your first post shows exactly this.

    Quote Originally Posted by monarch_dodra View Post
    I understand you can re-define all the typdefs yourself, or just do a total template specialisation for your iterator. But why can't you inherit?
    It's not that you can't inherit. It's just that you shouldn't. Why would you inherit from std::iterator_traits for this purpose? Even if you sub-class it and provide all those typedefs, what gets used inside the STL is std::iterator_traits and not your particular class derived from it. Got it?

    Quote Originally Posted by monarch_dodra View Post
    After all, isn't that how you implement a binary function, you inherit from binary_function<T,U>, you don't redefine the typedefs manually?
    With binary_function it's different. The roles they play are not the same. For instance, there are STL algorithms that let you parameterize the binary function that will be used. You're responsible for supplying the type. On the other hand, std::iterator_traits is not under your control. It's used inside the STL.

    Quote Originally Posted by monarch_dodra View Post
    Thank you very much for your input. It helps a lot. I don't want to make it look like I don't agree or apreciate your help.
    I'm just the kind of person who likes to understand how things work. I want more than the solution
    Don't worry. I don't think that. I'm also just trying to be usefull.

  9. #9
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: custom iterator

    Thank you very much ltcmelo. I haven't had time to read all the documentation, or look at the links, so I'll just sit back and take my time, try things out, and see if I understand everything or not. I'll come back later if I still have questions

    Quote Originally Posted by ltcmelo View Post
    Pointer don't need to define typedes because std::iterator_traits already provides an specialization for pointer types. In fact, that link you mentioned on your first post shows exactly this.
    I must admit I did not fully understand the page I was linking to. However, it is clearer now. Thanks.

  10. #10
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: custom iterator

    Quote Originally Posted by ltcmelo View Post
    If I recall correctly, there's no class in the boost iterator library that inherits from std::iterator_traits. What exactly do you mean?
    I mean you can inherit your iterator class from boost::iterator_facade and it will provide the appropriate typedefs required by std::iterator_traits.
    I understood monarch_dodra's remark as wanting to inherit his iterator class, rather than providing typedefs or specializing std::iterator_traits.
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  11. #11
    Join Date
    Jan 2006
    Location
    Belo Horizonte, Brazil
    Posts
    405

    Re: custom iterator

    Quote Originally Posted by D_Drmmr View Post
    I mean you can inherit your iterator class from boost::iterator_facade and it will provide the appropriate typedefs required by std::iterator_traits.
    I understood monarch_dodra's remark as wanting to inherit his iterator class, rather than providing typedefs or specializing std::iterator_traits.
    I see... Inheriting from an iterator class is ok, but inheriting from std::iterator_traits is another subject.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured