Err LNK2019 on ostream when templatizing class

Hi all,

So I have a linkedList class I am creating that I am trying to turn into a template. I put all of my information into a .h file. All methods seem to work, except for my ostream<< operator, for which I get this error from the compiler:

1>------ Build started: Project: myProject, Configuration: Debug Win32 ------
1> lab3.cpp
1>lab3.obj : error LNK2019: unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class List<class NodeData> const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABV?$List@VNodeData@@@@@Z) referenced in function _main
1>C:\Users\myName\documents\visual studio 2012\Projects\Project2\Debug\342Lab3.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Below is the relevant bit of code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
////////////////////////////////  list.h file  ///////////////////////////////
// Simple linked list, uses Node as linked list node

#ifndef LIST_H
#define LIST_H

#include <iostream>
#include <fstream>
using namespace std;

// Declaring this class as a template
template<class ItemType>

//--------------------------  class List  ------------------------------------
// ADT List: finite, ordered collection of zero or more items.
//           The ordering is determined by operator< of ItemType class.
//          
// Assumptions:  
//   -- Control of <, printing, etc. of ItemType information is in the 
//      ItemType class.  
//   -- There is no dummy head node, head points to first node.  
//      If the list is empty, head is NULL.
//   -- The insert allocates memory for a Node, ptr to the data is passed in.
//      Allocating memory and setting data is the responsibility of the caller.
//
// Note this definition is not a complete class and is not fully documented.
//----------------------------------------------------------------------------

class List {
   friend ostream &operator<<(ostream&, const List<ItemType>&);

public:
//Here I declare all the functions...

private:
//Here I declare the private members...

};

//Here I define the functions, which I have omitted for this post

	//----------------------------------------------------------------------------
	// operator<<  
	// output operator for class List, print data, 
	// responsibility for output is left to object stored in the list
	template<class ItemType>
	ostream& operator<<(ostream& output, const List<ItemType>& thelist) {
	   List::Node* current = thelist.head;
	   while (current != NULL) { 
		  output << *current->data;
		  current = current->next;
	   }
	   return output;                      // enables output << x << y;
	}

#ENDIF



Any ideas? I have searched online but I am still not sure what to do. Thanks for reading!
Last edited on
Fix these errors and try again.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
////////////////////////////////  list.h file  ///////////////////////////////
// Simple linked list, uses Node as linked list node

#ifndef LIST_H
#define LIST_H

#include <iostream>
#include <fstream>
using namespace std;

template < typename > class List ; // declare List<>

template<typename T> // declare the template function
ostream& operator<<(ostream& output, const List<T>& thelist) ;


// Declaring this class as a template
template<class ItemType>

//--------------------------  class List  ------------------------------------
// ADT List: finite, ordered collection of zero or more items.
//           The ordering is determined by operator< of ItemType class.
//
// Assumptions:
//   -- Control of <, printing, etc. of ItemType information is in the
//      ItemType class.
//   -- There is no dummy head node, head points to first node.
//      If the list is empty, head is NULL.
//   -- The insert allocates memory for a Node, ptr to the data is passed in.
//      Allocating memory and setting data is the responsibility of the caller.
//
// Note this definition is not a complete class and is not fully documented.
//----------------------------------------------------------------------------

class List {

   // this declares a friend function that is not a template
   // see: http://www.parashift.com/c++-faq-lite/template-friends.html
   // friend ostream &operator<<(ostream&, const List<ItemType>&);

   // declare the function as a template friend ( with <> )
   friend ostream &operator<< <> (ostream&, const List<ItemType>&);

public:
//Here I declare all the functions...

private:
//Here I declare the private members...
};

//Here I define the functions, which I have omitted for this post

	//----------------------------------------------------------------------------
	// operator<<
	// output operator for class List, print data,
	// responsibility for output is left to object stored in the list
	template<class ItemType>
	ostream& operator<<(ostream& output, const List<ItemType>& thelist) {

	   //List::Node* current = thelist.head; // *** error, List<> is a template
	   // Node is a dependant name; must be disambiguated with 'typename'
	   typename List<ItemType>::Node* current = thelist.head;

	   while (current != NULL) {
		  output << *current->data;
		  current = current->next;
	   }
	   return output;                      // enables output << x << y;
	}

// #ENDIF // *** error
#endif 
When you would start listening to your compiler
30: warning: friend declaration ‘std::ostream& operator<<(std::ostream&, const List<ItemType>&)’ declares a non-template function [-Wnon-template-friend]
note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) 
In line 47 you define a template function, but the friend was not a template.

To fix it
1. Don't separate declaration and definition (define the function in line 30)
a.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template <class T> class List; //forward declare
template<class T>
std::ostream& operator<<(std::ostream&, const List<T>&); //so you can declare the function

template<ItemType>
class List{
   //as the note say, we are friends of a template function
   std::ostream& operator<< <>(std::ostream&, const List<T>&);
   //...
};

template<class T>
std::ostream& operator<<(std::ostream&, const List<T>&){
   //...
}
is this is for the recursive call and placing strings in link list notes
Solved, thanks guys!
Topic archived. No new replies allowed.