Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't the compiler differentiate between typedef and non-typedef?

Sorry for the long title.

I have a typedef in a class List:

template <typename T>
class List { 
    // Think of a class Iter_ with ListElem *pCurrentPos and List *pList
    typedef const Iter_ const_iterator; 

    const_iterator cbegin() const;
};

and the definition outside of the class, but inside the header file.

template <typename T>
typename List<T>::const_iterator List<T>::cbegin() const {}

This produces the error C2373: Redefinition; different type modifiers

I rewrote the function like so:

template <typename T>
const typename List<T>::Iter_ List<T>::cbegin() const {}

and the error is gone; the program compiles correctly. (think away the fact I'm not returning anything in these examples; it's irrelevant to the example.)

What is the compiler interpreting with the erroneous version that prevents successful compilation that the second version does not, and how can I remedy this?

More Code

I'm using VS2008

The (fuller) code example I'm currently programming:

template <typename T>
class List
{
public:
    // Forward declaration.
    class Iter_;

private:
    /////////////////////////////////////////////////////////
    // ListElem
    /////////////////////////////////////////////////////////
    struct ListElem
    {
        T data;
        // Doubly-linked list.
        ListElem *next;
        ListElem *prev;
    };

    class ListException {};

    ////////////////////////////////////////////////////////
    // List Members
    ////////////////////////////////////////////////////////
    // Point to first elem.
    ListElem *head_;
    // Point to last elem.
    ListElem *tail_;

public:
    //////////////////////////////////////////////////////////
    // Typedefs
    //////////////////////////////////////////////////////////
    typedef       Iter_   iterator;
    typedef const Iter_   const_iterator;

    //////////////////////////////////////////////////////////
    // Iterator class
    //////////////////////////////////////////////////////////
    class Iter_
    {
    public:
        Iter_( ListElem *pCurr, List *pList )
            : pCurr_(pCurr), pList_(pList)
        {       }

        T& operator*()
        {
            if( *this == pList_->end() )
                throw ListException();
            else
                return pCurr_->data;
        }

    private:
        ListElem *pCurr_;
        List     *pList_;
    };

iterator begin();
iterator end();

const_iterator cbegin() const;
const_iterator cend()   const;
};

template <typename T>
List<T>::List()
    : head_(0), tail_(0), size_(0)
{   }

template <typename T>
List<T>::~List()
{
    //this->clear();
}

template <typename T>
List<T>::List( List const& other )
    : size_(other.size_)
{
    //this->clone(other);
}

template <typename T>
List<T>& List<T>::operator=( List const& other )
{
    size_ = other.size_;
    //this->clone(other);
}

// Compiles ok
template <typename T>
typename List<T>::iterator List<T>::begin()
{
    if(!head_)
        head_ = new ListElem();
    return iterator(head_, this);
}

// Compiles ok
template <typename T>
typename List<T>::iterator List<T>::end()
{
    return iterator(tail_, this);
}

// Compiler error
template <typename T>
typename List<T>::const_iterator List<T>::cbegin() const
{
    return const_iterator(head_, this);
}

// Compiles ok
template <typename T>
typename const List<T>::Iter_ List<T>::cend() const
{
    return const_iterator(tail_, this);
}
like image 843
IAE Avatar asked Feb 25 '23 13:02

IAE


1 Answers

The error I get when instantiating cbegin() is that you are passing (const) this to the constructor which takes a non-const pointer to the List.

Basically I doubt this idea works that well.

 typedef const Iter_   const_iterator;
like image 110
UncleBens Avatar answered Mar 09 '23 05:03

UncleBens