Question

So I have this templated class called list

//List.h
#ifndef LIST_H
#define LIST_H
#include<fstream>

template <class T>
class List
{
    private:
        struct ListNode
        {
           T value;
           ListNode* next;
           ListNode* prev;

           ListNode(T value1, ListNode* next1 = NULL, ListNode* prev1 = NULL)
           {
            value = value1;
            next = next1;
            prev = prev1;
           }
        };
        ListNode* head;
        ListNode* tail;

   public:
       List() {head = NULL; tail = NULL;};
       ~List();
       void PrintForward(std::ostream &out);
       void PrintBackward(std::ostream &out);
       void InsertFront(const T &item);
       void InsertRear(const T &item);
       bool InsertAsNth(int N, const T &item);
       bool DeleteFront(T &val);
       bool DeleteRear(T &val);
       bool DeleteNth(int N, T &val);
       int DeleteAllOccur(const T &item);

       std::ostream& operator<< (std::ostream &out, List::ListNode const* p);

};
#endif

Now I have been trying to get this to compile but with no success. I know it has to do with the way I have the ostream operator overloaded but unfortunately I really do not know/could not find a better way.

also this is my compiler error

 warning C4346: 'List<T>::ListNode' : dependent name is not a type prefix with 'typename' to indicate a type
Was it helpful?

Solution

std::ostream& operator<< (std::ostream &out, List::ListNode const* p);

has to become

std::ostream& operator<< (std::ostream &out, typename List::ListNode const* p);

or maybe even

std::ostream& operator<< (std::ostream &out, typename List<T>::ListNode const* p);

to be more explicit.

Because ::ListNode is a dependant type of the templated class List and the C++ compiler needs a little hint there. The warning is actually surprisingly helpful in this case, which cannot be said for many template related ones :)

OTHER TIPS

The compiler error says exactly what is wrong and what you have to do: List<T>::Node is a qualified-id dependent on a template parameter, so the compiler cant be sure if Node is a type or a value. So you have to write typename before it to tell the compiler that Node is a type.

I suggest you to checkout this question: Where and why do I have to put the "template" and "typename" keywords?

There are at least two major problems with your code. The most critical is that you are making operator<< a member, and trying to give it three parameters, Which is completely illegal. If the first parameter is to be an std::ostream&, there is no way you can define it as a member; it must be a free function. If it also needs access to private data, then you'll have to make it a friend. But be aware:

friend std::ostream& operator<<( std::ostream&, typename List::ListNode const* );

makes a non-template function friend. A different non-template function for each instantiation of the template. This is rarely what is wanted. You can make a specific template instantiation friend, but only if the template function is declared before hand. Which is impossible in this case, because one of the arguments of the function has a nested type. The more idiomatic way of solving this (in my experience, anyway) is to define the friend inline:

friend std::ostream& operator<<( std::ostream& dest, typename List::ListNode const& p )
{
    //  ...
}

In this case, operator<< is also a non-templated function, but the definition is nested in the class template, so you will get a new instance of the function automatically.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top