Thread: circular iterator question

  1. #1
    Use this: dudeomanodude's Avatar
    Join Date
    Jan 2008
    Location
    Hampton, VA
    Posts
    391

    circular iterator question

    In a previous thread we were talking about circular iterators, here's the thread.

    I'm looking at laserlight's example. CornedBee then says that the circular_iterator is not assignable because of the reference member.

    Does that mean every time you want an iterator to be located somewhere else, like back to the beginning, you need to declare a new iterator?

    How do you change that? (In other words, how would the class structure/constructors change to accomidate assignability)?
    Ubuntu Desktop
    GCC/G++
    Geany (for quick projects)
    Anjuta (for larger things)

  2. #2
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Change the reference to a pointer (as was mentioned later in that thread). Pointers can be assigned, and since the pointed to object isn't owned by the iterator, the copying done on assignment is straightforward.

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Change the reference to a pointer
    Indeed, I mentioned that in that thread.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Use this: dudeomanodude's Avatar
    Join Date
    Jan 2008
    Location
    Hampton, VA
    Posts
    391
    Sorry about that. I found it.
    Ubuntu Desktop
    GCC/G++
    Geany (for quick projects)
    Anjuta (for larger things)

  5. #5
    Use this: dudeomanodude's Avatar
    Join Date
    Jan 2008
    Location
    Hampton, VA
    Posts
    391
    Okay, can someone please explain the output of this program (assigning doesn't seem to be working) and the iterator seems to print the last element (5) twice?

    Code:
    #include <iostream>
    #include <list>
    
    template <typename T>
    class circular_iterator{
    
    	public:
    	
                circular_iterator(){};
    		
    	    circular_iterator( typename std::list<T>::iterator iter )
    	    : iter(iter) {};
    		
    	    circular_iterator& operator++(){
            
            	if ( iter != container->end() ){
                
                	    ++iter;
            	}
            
            	else{
                
                	    iter = container->begin();
            	}
            
            	return *this;
        	    }
        	
        	    circular_iterator& operator--(){
        		
        		if ( iter != container->rend() ){
        			
        			--iter;
        		}
        		
        		else{
        			
        			iter = container->rbegin();
        		}
        		
        		return *this;
        	    }
        	
        	    T& operator*(){
            
            	return *iter;
        	    }
    
        	    bool operator!=( circular_iterator rhs ) const{
            
            	return iter != rhs.iter;
        	    }
    	
    	private:
    	
                std::list<T>* container;
    	    typename std::list<T>::iterator iter;
    };
    
    
    int main(){
    	
    	std::list<int> numbers;
    	for( int n = 0; n < 5; n++ ){
    		
    		numbers.push_back( n + 1 );
    	}
    	
    	circular_iterator<int> it = numbers.begin();
    	for( int n = 0; n < 13; n++ ){
    		
    		std::cout << *it << " ";
    		++it;
    	}
    	
    	it = numbers.begin();
    	std::cout << *it << "\n";
    	
    	return 0;
    }
    Output:
    Code:
    1 2 3 4 5 -1078047976 1 2 3 4 5 -1078047976 1 1
    Ubuntu Desktop
    GCC/G++
    Geany (for quick projects)
    Anjuta (for larger things)

  6. #6
    Use this: dudeomanodude's Avatar
    Join Date
    Jan 2008
    Location
    Hampton, VA
    Posts
    391
    I don't mean to annoy you guys, it's just that in the previous thread you guys showed me a lot of stuff I've never seen before and I'd like to understand it.
    Ubuntu Desktop
    GCC/G++
    Geany (for quick projects)
    Anjuta (for larger things)

  7. #7
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    I would check if the iterator was equal to the end() after incrementing it, and then move it to the beginning then. Otherwise, there is one time when the iterator points to end(), which is one past the last valid element and shouldn't actually be used.

    By the way, where is container initialized? I don't see it.

  8. #8
    Use this: dudeomanodude's Avatar
    Join Date
    Jan 2008
    Location
    Hampton, VA
    Posts
    391
    Quote Originally Posted by Daved View Post
    By the way, where is container initialized? I don't see it.
    If I change the constructor to:
    Code:
    circular_iterator( std::list<T> * container, typename std::list<T>::iterator iter )
    : container( container ), iter(iter) {};
    It doesn't compile, complains that:
    Code:
    main.cpp: In function ‘int main()’:
    main.cpp:69: error: conversion from ‘std::_List_iterator<int>’ to non-scalar type ‘circular_iterator<int>’ requested
    main.cpp:76: error: no match for ‘operator=’ in ‘it = numbers.std::list<_Tp, _Alloc>::begin [with _Tp = int, _Alloc = std::allocator<int>]()’
    main.cpp:5: note: candidates are: circular_iterator<int>& circular_iterator<int>::operator=(const circular_iterator<int>&)
    which of course, I don't understand what this 'conversion to non-scalar type' is all about.
    Ubuntu Desktop
    GCC/G++
    Geany (for quick projects)
    Anjuta (for larger things)

  9. #9
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    What line does it refer to? This:
    Code:
    circular_iterator<int> it = numbers.begin();
    will no longer work.

  10. #10
    Use this: dudeomanodude's Avatar
    Join Date
    Jan 2008
    Location
    Hampton, VA
    Posts
    391
    Quote Originally Posted by Daved View Post
    What line does it refer to? This:
    Code:
    circular_iterator<int> it = numbers.begin();
    will no longer work.
    right, that's the line it was referring to.

    Is std::list<T>* container even necessary? I mean, can't I just have the iterator as the member and overload the necessary operators?
    Ubuntu Desktop
    GCC/G++
    Geany (for quick projects)
    Anjuta (for larger things)

  11. #11
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    The simple answer is that you changed the constructor of the class, so of course you'll get an error if you don't change the code that calls the constructor.

    >> Is std::list<T>* container even necessary?
    But you use container in the class, so how else are you going to get that behavior? You can't get the container from the iterator (although you can get an iterator from the container).

    Are you trying to do this without looking at laserlight's version? Because there is an answer there.

  12. #12
    Use this: dudeomanodude's Avatar
    Join Date
    Jan 2008
    Location
    Hampton, VA
    Posts
    391
    Quote Originally Posted by Daved View Post
    The simple answer is that you changed the constructor of the class, so of course you'll get an error if you don't change the code that calls the constructor.

    >> Is std::list<T>* container even necessary?
    But you use container in the class, so how else are you going to get that behavior? You can't get the container from the iterator (although you can get an iterator from the container).

    Are you trying to do this without looking at laserlight's version? Because there is an answer there.
    Well at first I tried simply replacing the reference in laserlight's example with a pointer, but that didn't work.

    So then I tried building it from the ground up (although I was still pretty much stealing her example), but I did so without inheriting the forward_iterator (mainly because I don't really know what to do with that).

    I know what you're saying, that I need the container to do things like container.begin() or container.end().

    I don't know. I'm just kinda lost right now. My goal is to implement laserlight's example, but use a pointer to the container and allow for assignability.

    Perhaps a clue?
    Ubuntu Desktop
    GCC/G++
    Geany (for quick projects)
    Anjuta (for larger things)

  13. #13
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> Well at first I tried simply replacing the reference in laserlight's example with a pointer, but that didn't work.

    It is probably a simple thing you did wrong. I might go back to laserlight's version and make the change to a pointer, then ask for help if you can't fix the error you get. It might be something simple like forgetting to pass a pointer to the constructor instead of passing the container directly.

    You could also try CornedBee's example, I think perhaps the consensus was that it might be an even better way to go.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Circular Positioning in C# form application?
    By arcaine01 in forum C# Programming
    Replies: 4
    Last Post: 05-08-2008, 02:31 PM
  2. Circular Lists
    By dudeomanodude in forum C++ Programming
    Replies: 65
    Last Post: 03-05-2008, 09:26 PM
  3. singly linked circular list
    By DarkDot in forum C++ Programming
    Replies: 0
    Last Post: 04-24-2007, 08:55 PM
  4. Circular include issue
    By einarp in forum C++ Programming
    Replies: 10
    Last Post: 07-10-2006, 08:43 PM
  5. circular shift
    By n00bcodezor in forum C Programming
    Replies: 2
    Last Post: 11-20-2001, 03:51 AM