Jump to content
  • Advertisement
Sign in to follow this  
toogreat4u

Compile Error

This topic is 3524 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am trying to play around with templates and I am coming across a strange error and it is strictly related to using the ostream function function in header file:
#include <iostream>
using namespace std;

friend ostream& operator <<(ostream& outs, const GenericList<ItemType>& the_list);
	// Overlaods the << operator so it can be used to output the contents of the list.
	// The items are output one per line.
	// Precondition: If outs is a file output stream, then outs has already been connected to a file

function definition in cpp file:

#include <iostream>
#include <cstdlib>
#include "genericlist.h"

template<class ItemType>
ostream& operator <<(ostream& outs, const GenericList<ItemType>& the_list)
{
	for(int i = 0; i < the_list.current_length; i++)
		outs << the_list.item << endl;
	return outs;
}

This is how I am calling it in the driver file:
#include <iostream>
#include "genericlist.h"
#include "genericlist.cpp"
using namespace std;

GenericList<int> first_list(2);
	first_list.add(1);
	first_list.add(2);
	cout << "first_list = \n" << first_list;

It is giving me a link error and I am absolutely confused as to why: 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 GenericList<int> const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABV?$GenericList@H@@@Z) referenced in function _main 1>C:\Documents and Settings\gdesigner\Desktop\Problem Solving with C++ 5th Edition\Chapter 14\Project 2\Debug\Project 2.exe : fatal error LNK1120: 1 unresolved externals 1>Build log was saved at "file://c:\Documents and Settings\gdesigner\Desktop\Problem Solving with C++ 5th Edition\Chapter 14\Project 2\Project 2\Debug\BuildLog.htm"

Share this post


Link to post
Share on other sites
Advertisement
I assume the driver code is in some kind of function?

Either way, the issue is that on most compilers the template implementation must be available when you try to use it. More simply, if you leave the implementation in the header file it will work.

What is GenericList? Any reason you are avoiding the standard containers?

Share this post


Link to post
Share on other sites
Thank you. Reason I am doing it this way is for learning purposes, plus its from a book and this is the way they designed there class structure.

Share this post


Link to post
Share on other sites
Ok so the fix suggested didnt work so when I commented out the cout statements it compiled perfectly. I'll go ahead and show the whole header and definiton for genericlist, and the driver function.

Header:

#ifndef GENERICLIST_H
#define GENERICLIST_H

#include <iostream>
using namespace std;

template<class ItemType>
class GenericList
{
public:
GenericList(int max);
// Initializes the object to an empty list that can hold up to max items of type ItemType

~GenericList();
// Returns all the dynamic memory used by the project to the freestore

int length() const;
// returns the number of items on the list

void add(ItemType new_item);
// Precondition: The list is not full
// Postcondition: the new_item has been added to the list

bool full() const;
// returns true if the list is full

void erase();
// removes all items from the list so that the list is empty

friend ostream& operator <<(ostream& outs, const GenericList<ItemType>& the_list);
// Overlaods the << operator so it can be used to output the contents of the list.
// The items are output one per line.
// Precondition: If outs is a file output stream, then outs has already been connected to a file
private:
ItemType *item; // pointer to the dynamic array that holds the list
int max_length; // max number of items allowed on the list
int current_length; // number of items currently on the list
};
#endif



Definition file for GenericList

#ifndef GENERICLIST_CPP
#define GENERICLIST_CPP

#include <iostream>
#include <cstdlib>
#include "genericlist.h"

using namespace std;

template<class ItemType>
GenericList<ItemType>::GenericList(int max): max_length(max), current_length(0)
{
item = new ItemType[max];
}

template<class ItemType>
GenericList<ItemType>::~GenericList()
{
delete [] item;
}

template<class ItemType>
int GenericList<ItemType>::length() const
{
return current_length;
}

template<class ItemType>
void GenericList<ItemType>::add(ItemType new_item)
{
if(full())
{
cout << "Error: adding to a full list.\n";
exit(1);
}
else
{
item[current_length] = new_item;
current_length = current_length + 1;
}
}

template<class ItemType>
bool GenericList<ItemType>::full() const
{
return (current_length == max_length);
}

template<class ItemType>
void GenericList<ItemType>::erase()
{
current_length = 0;
}

template<class ItemType>
ostream& operator <<(ostream& outs, const GenericList<ItemType>& the_list)
{
for(int i = 0; i < the_list.current_length; i++)
outs << the_list.item << endl;
return outs;
}

#endif



Driver program:

#include <iostream>
#include "genericlist.h"
#include "genericlist.cpp"
using namespace std;

int main()
{
GenericList<int> first_list(2);
first_list.add(1);
first_list.add(2);
cout << "first_list = \n" << first_list;

GenericList<char> second_list(10);
second_list.add('A');
second_list.add('B');
second_list.add('C');
cout << "second list = \n" << second_list;
return 0;
}

Share this post


Link to post
Share on other sites
Quote:
Source: Me
More simply, if you leave the implementation in the header file it will work.

Your template implementations aren't in the header file.

Quote:

Ok so the fix suggested didnt work...

What fix did you think I was talking about?

Share this post


Link to post
Share on other sites
I think you really just can't put implementation of a template class in a separate cpp file.

Another thing is that friends to templates are a very tricky business.

Actually one would expect that your GenericList provides some kind of accessors, so that operator>> could be implemented as non-friend using the public interface of the container.

Share this post


Link to post
Share on other sites
The fix I was referring to was the fix about placing all the defintions in the header file which still gave me the compiling errors. However the link visitor gave cleared up any of the confusion I had about what was going on. Thank you both for your responses. I simply defined the friend operator inside of the class.


friend ostream& operator <<(ostream& outs, const GenericList<ItemType>& the_list)
{
for(int i = 0; i < the_list.current_length; i++)
outs << the_list.item << endl;
return outs;
}



Is this a specific compiler issue with VC++ 2008? Because on a linux machine I never got this problem. Thanks for the help

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!