[C++] Class Code Question

Discussion in 'Mixed Languages' started by CODYQX4, Oct 30, 2010.

  1. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,810
    45,356
    150
    #1 CODYQX4, Oct 30, 2010
    Last edited by a moderator: Apr 20, 2017
    OK I have this code and I need for the class to have an iterator that has the properties listed below (see I have oveloaded operators).

    I need the iterator to be a part of the class and declared to start at the beginning of the list I declared. It should be accessible to any function I add to the class.

    My problem is no method I try does this, either it throws a compiler error or does not inherit the operators and is therefore useless. This code relates to other code so I cannot radically alter it or things will break.

    How would I do this? I've tried it all week and I'm starting to think its impossible as nothing this simple should be so hard.
    Code:
    #include <iostream>
    #include <list>
    #include <string>
    
    using namespace std;
    
    template<class T>
    class Ring
    {
            list<T> lst;
    
        public:
    
            // Forward declarations for class iterator
            // 
            // Without these declarations, the Ring
            // class would see std::iterator instead of
            // its own iterator
    
            class iterator;
            friend class iterator;
            
            // We can't use std::iterator "out of the box" because it doesn't
            // "know" how to loop back around a circular list. So we are
            // creating a child class based on std::iterator, then "teaching" it
            // how to loop back around. The main difference is in the code for 
            // operator++ and operator--().
    
            class iterator : public std::iterator<
                        std::bidirectional_iterator_tag,T,ptrdiff_t>
            {
                    // The "typename" construct is sometimes required in C++
                    // to force the compiler to recognize something as a data
                    // type. In the line below, we are forcing the compiler to
                    // recognize "T" as a data type. This kind of hack is
                    // often needed when declaring template iterators.
                    
                    typename list<T>::iterator it;
                    list<T>* r;
    
                public:
                    iterator( list<T>& lst,
                              const typename list<T>::iterator& i )
                            : r( &lst ), it( i ) {}
    
                    bool operator==( const iterator& x ) const
                    {
                        return it == x.it;
                    }
    
                    bool operator!=( const iterator& x ) const
                    {
                        return !( *this == x );
                    }
    
                    typename list<T>::reference operator*() const
                    {
                        return *it;
                    }
    
                    iterator& operator++()
                    {
                        ++it;
                        if ( it == r->end() )
                            it = r->begin();
                        return *this;
                    }
    
                    iterator operator++( int )
                    {
                        iterator tmp = *this;
                        ++*this;
                        return tmp;
                    }
    
                    iterator& operator--()
                    {
                        if ( it == r->begin() )
                            it = r->end();
                        --it;
                        return *this;
                    }
    
                    iterator operator--( int )
                    {
                        iterator tmp = *this;
                        --*this;
                        return tmp;
                    }
    
                    iterator insert( const T& x )
                    {
                        return iterator( *r, r->insert( it, x ) );
                    }
    
                    iterator erase()
                    {
                        return iterator( *r, r->erase( it ) );
                    }
    
            };
            
            // The interface for Ring is fairly sparse. Note that we have not
            // made it possible to go to the "end" of a ring by using "end()"
            // since a ring has no true end.
            
            void push_back( const T& x )
            {
                lst.push_back( x );
            }
    
            iterator begin()
            {
                return iterator( lst, lst.begin() );
            }
    
            int size()
            {
                return lst.size();
            }
    };
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  2. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,810
    45,356
    150
    Ugh I forgot the [] around the C++ in title. sorry, I was up late over this in vain...
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  3. BobSheep

    BobSheep MDL Guru

    Apr 19, 2010
    2,326
    1,362
    90
    I have sent you a PM.
    I think once you are happy with your code it could be useful to post it here, after the cutoff time for your project to be assessed of course.
     
  4. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,810
    45,356
    150
    #4 CODYQX4, Nov 1, 2010
    Last edited: Nov 1, 2010
    (OP)
    I'll test it soon, but the main() code in Ring() was known to work and we want the main() in RingTest.cpp to work.

    EDIT: No luck, I still can't declare the iterator the way I need to.

    You said there were compile errors in 2008? I did not get any as long as the iterator code was not there.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  5. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,810
    45,356
    150
    I resolved it with this:
    typename list<T>::iterator cursor;

    above my functions, and showStructure is first used so it sets it to beginning the first time its called (by checking if the list is empty), as I could not declare it in the class.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  6. truman

    truman MDL Novice

    Jan 17, 2009
    8
    0
    0
    #6 truman, Nov 2, 2010
    Last edited by a moderator: Apr 20, 2017
    If you using MS Visual Studio C++ then your problem lies with this:

    Code:
    class iterator : public std::iterator<
                        std::bidirectional_iterator_tag,T,ptrdiff_t>
    It should be like this:

    Code:
    class iterator : public list<T>::iterator
     
  7. truman

    truman MDL Novice

    Jan 17, 2009
    8
    0
    0
    #7 truman, Nov 2, 2010
    Last edited by a moderator: Apr 20, 2017
    This compiles and works under MS Visual Studio 2008 C++:

    Code:
    #include <iostream>
    #include <list>
    
    using namespace std;
    
    template<class T>
    class Ring
    {
            list<T> lst;
    
        public:
    
            // Forward declarations for class iterator
            // 
            // Without these declarations, the Ring
            // class would see std::iterator instead of
            // its own iterator
    
            class iterator;
            //friend class iterator;
            
            // We can't use std::iterator "out of the box" because it doesn't
            // "know" how to loop back around a circular list. So we are
            // creating a child class based on std::iterator, then "teaching" it
            // how to loop back around. The main difference is in the code for 
            // operator++ and operator--().
    
            class iterator : public list<T>::iterator
            {
                    // The "typename" construct is sometimes required in C++
                    // to force the compiler to recognize something as a data
                    // type. In the line below, we are forcing the compiler to
                    // recognize "T" as a data type. This kind of hack is
                    // often needed when declaring template iterators.
                    
                    typename list<T>::iterator it;
                    list<T>* r;
    
                public:
                    iterator() {}
                    iterator( list<T>& lst,
                              const typename list<T>::iterator& i )
                            : r( &lst ), it( i ) {}
    
                    bool operator==( const iterator& x ) const
                    {
                        return it == x.it;
                    }
    
                    bool operator!=( const iterator& x ) const
                    {
                        return !( *this == x );
                    }
    
                    typename list<T>::reference operator*() const
                    {
                        return *it;
                    }
    
                    iterator& operator++()
                    {
                        ++it;
                        if ( it == r->end() )
                            it = r->begin();
                        return *this;
                    }
    
                    iterator operator++( int )
                    {
                        iterator tmp = *this;
                        ++*this;
                        return tmp;
                    }
    
                    iterator& operator--()
                    {
                        if ( it == r->begin() )
                            it = r->end();
                        --it;
                        return *this;
                    }
    
                    iterator operator--( int )
                    {
                        iterator tmp = *this;
                        --*this;
                        return tmp;
                    }
    
                    iterator insert( const T& x )
                    {
                        return iterator( *r, r->insert( it, x ) );
                    }
    
                    iterator erase()
                    {
                        return iterator( *r, r->erase( it ) );
                    }
    
            };
            
            // The interface for Ring is fairly sparse. Note that we have not
            // made it possible to go to the "end" of a ring by using "end()"
            // since a ring has no true end.
            
            void push_back( const T& x )
            {
                lst.push_back( x );
            }
    
            iterator begin()
            {
                return iterator( lst, lst.begin() );
            }
    
            int size()
            {
                return lst.size();
            }
    };
    
    int main()
    {
        Ring<int> r;
        Ring<int>::iterator it;
        int i;
    
        //Push test values.
        r.push_back(1);
        r.push_back(2);
        r.push_back(3);
    
        //Display values.
        it = r.begin();
        for(i = 0; i < 6; i++)
        {
            cout << *it << endl;
            it++;
        }
    
        return 0;
    }
     
  8. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,810
    45,356
    150
    I was not allowed to change that but my above fix worked without any issues.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...