Reputation: 29
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
Upvotes: 0
Views: 461
Reputation: 153919
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.
Upvotes: 0
Reputation: 14174
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?
Upvotes: 1
Reputation: 21194
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 :)
Upvotes: 3