CodeGuru Forums -
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic Newsletters VB Forums Developer.com


Newest CodeGuru.com Articles:

  • Faltering Windows support
  • Internet Explorer 8 Click Clever Click Safe
  • Release Candidate 2 for ASP.NET MVC 2
  • Learn How to Create Dual Mode Windows Services

  • Search CodeGuru:
     



    Go Back   CodeGuru Forums > Visual C++ & C++ Programming > C++ (Non Visual C++ Issues)
    FAQ Members List Calendar Search Today's Posts Mark Forums Read

    C++ (Non Visual C++ Issues) Ask or answer C and C++ questions not related to Visual C++. This includes Console programming, Linux programming, or general ANSI C++.

    Reply
     
    Thread Tools Search this Thread Rate Thread Display Modes
      #1    
    Old August 5th, 2009, 09:29 AM
    monarch_dodra monarch_dodra is online now
    Member
     
    Join Date: Jun 2009
    Posts: 389
    monarch_dodra will become famous soon enough (80+)
    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?
    Reply With Quote
      #2    
    Old August 5th, 2009, 10:18 AM
    ltcmelo ltcmelo is offline
    Member
     
    Join Date: Jan 2006
    Location: Belo Horizonte, Brazil
    Posts: 387
    ltcmelo is a jewel in the rough (200+) ltcmelo is a jewel in the rough (200+) ltcmelo is a jewel in the rough (200+)
    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?
    Reply With Quote
      #3    
    Old August 5th, 2009, 10:49 AM
    monarch_dodra monarch_dodra is online now
    Member
     
    Join Date: Jun 2009
    Posts: 389
    monarch_dodra will become famous soon enough (80+)
    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.
    Reply With Quote
      #4    
    Old August 5th, 2009, 11:40 AM
    ltcmelo ltcmelo is offline
    Member
     
    Join Date: Jan 2006
    Location: Belo Horizonte, Brazil
    Posts: 387
    ltcmelo is a jewel in the rough (200+) ltcmelo is a jewel in the rough (200+) ltcmelo is a jewel in the rough (200+)
    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.
    Reply With Quote
      #5    
    Old August 5th, 2009, 12:08 PM
    monarch_dodra monarch_dodra is online now
    Member
     
    Join Date: Jun 2009
    Posts: 389
    monarch_dodra will become famous soon enough (80+)
    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::distance, 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
    Reply With Quote
      #6    
    Old August 5th, 2009, 12:13 PM
    D_Drmmr's Avatar
    D_Drmmr D_Drmmr is offline
    Member
     
    Join Date: Jul 2005
    Location: Netherlands
    Posts: 442
    D_Drmmr is a jewel in the rough (200+) D_Drmmr is a jewel in the rough (200+) D_Drmmr is a jewel in the rough (200+)
    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
    Reply With Quote
      #7    
    Old August 5th, 2009, 01:18 PM
    ltcmelo ltcmelo is offline
    Member
     
    Join Date: Jan 2006
    Location: Belo Horizonte, Brazil
    Posts: 387
    ltcmelo is a jewel in the rough (200+) ltcmelo is a jewel in the rough (200+) ltcmelo is a jewel in the rough (200+)
    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?
    Reply With Quote
      #8    
    Old August 5th, 2009, 01:37 PM
    ltcmelo ltcmelo is offline
    Member
     
    Join Date: Jan 2006
    Location: Belo Horizonte, Brazil
    Posts: 387
    ltcmelo is a jewel in the rough (200+) ltcmelo is a jewel in the rough (200+) ltcmelo is a jewel in the rough (200+)
    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::distance, 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.
    Reply With Quote
      #9    
    Old August 5th, 2009, 02:10 PM
    monarch_dodra monarch_dodra is online now
    Member
     
    Join Date: Jun 2009
    Posts: 389
    monarch_dodra will become famous soon enough (80+)
    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.
    Reply With Quote
      #10    
    Old August 5th, 2009, 02:47 PM
    D_Drmmr's Avatar
    D_Drmmr D_Drmmr is offline
    Member
     
    Join Date: Jul 2005
    Location: Netherlands
    Posts: 442
    D_Drmmr is a jewel in the rough (200+) D_Drmmr is a jewel in the rough (200+) D_Drmmr is a jewel in the rough (200+)
    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
    Reply With Quote
      #11    
    Old August 5th, 2009, 03:19 PM
    ltcmelo ltcmelo is offline
    Member
     
    Join Date: Jan 2006
    Location: Belo Horizonte, Brazil
    Posts: 387
    ltcmelo is a jewel in the rough (200+) ltcmelo is a jewel in the rough (200+) ltcmelo is a jewel in the rough (200+)
    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.
    Reply With Quote
    Reply

    Bookmarks
    Go Back   CodeGuru Forums > Visual C++ & C++ Programming > C++ (Non Visual C++ Issues)


    Thread Tools Search this Thread
    Search this Thread:

    Advanced Search
    Display Modes Rate This Thread
    Rate This Thread:

    Posting Rules
    You may not post new threads
    You may not post replies
    You may not post attachments
    You may not edit your posts

    BB code is On
    Smilies are On
    [IMG] code is On
    HTML code is Off
    Forum Jump


    All times are GMT -5. The time now is 08:57 AM.



    Acceptable Use Policy


    The Network for Technology Professionals

    Search:

    About Internet.com

    Legal Notices, Licensing, Permissions, Privacy Policy.
    Advertise | Newsletters | E-mail Offers


    Powered by vBulletin® Version 3.7.3
    Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.