There was no detected errors on the code but there was still undefined reference problems:
MAIN.cpp:(.text+0x64): undefined reference to `listsavitch::operator<<(std::ostream&, listsavitch::List<int> const&)'
MAIN.cpp:(.text+0xca): undefined reference to `listsavitch::operator<<(std::ostream&, listsavitch::List<char> const&)'
list.cpp
//This is the implementation file: list.cpp
//This is the implementation of the class template named List.
//The interface for the class template List is in the header file list.h.
#ifndef LIST_CPP
#define LIST_CPP
#include <iostream>
#include <cstdlib>
#include "list.h"//This is not needed when used as we are using this file,
//but the #ifndef in list.h makes it safe.
using namespace std;
namespace listsavitch
{
//Uses cstdlib:
template<class ItemType>
List<ItemType>::List(int max) : max_length(max), current_length(0)
{
item = new ItemType[max];
}
template<class ItemType>
List<ItemType>::~List( )
{
delete [] item;
}
template<class ItemType>
int List<ItemType>::length( ) const
{
return (current_length);
}
//Uses iostream and cstdlib:
template<class ItemType>
void List<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 List<ItemType>::full( ) const
{
return (current_length == max_length);
}
template<class ItemType>
void List<ItemType>::erase( )
{
current_length = 0;
}
//Uses iostream:
template<class ItemType>
ostream& operator <<(ostream& outs, const List<ItemType>& the_list)
{
for (int i = 0; i < the_list.current_length; i++)
outs << the_list.item[i] << endl;
return outs;
}
}//listsavitch
#endif // LIST_CPP Notice that we have enclosed all the template
// definitions in #ifndef... #endif.
[/code]
[MAIN]
//Program to demonstrate use of the class template List.
#include <iostream>
#include "list.h"
#include "list.cpp"
using namespace std;
using namespace listsavitch;
int main( )
{
List<int> first_list(2);
first_list.add(1);
first_list.add(2);
cout << "first_list = \n"
<< first_list;
List<char> second_list(10);
second_list.add('A');
second_list.add('B');
second_list.add('C');
cout << "second_list = \n"
<< second_list;
return 0;
}
[endMAIN]
[list.h]
//This is the header file list.h. This is the interface for the class List.
//Objects of type List can be a list of items of any type for which the operators
//<< and = are defined. All the items on any one list must be of the same type. A
//list that can hold up to max items all of type Type_Name is declared as follows:
// List<Type_Name> the_object(max);
#ifndef LIST_H
#define LIST_H
#include <iostream>
using namespace std;
namespace listsavitch
{
template<class ItemType>
class List
{
public:
List(int max);
//Initializes the object to an empty list that can hold up to
//max items of type ItemType.
~List( );
//Returns all the dynamic memory used by the object to the free store.
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 List<ItemType>& the_list);
//Overloads 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.
};
}//listsavitch
#endif //LIST_H
[end code/]
@beginnerzzzzz,
There are some undesirable ways around it, but template'd functions are usually defined inside header files (or a file that gets #include'd in the header file). The file containing the definition is sometimes given extension .hpp instead (but people have their own preferences).
Please use code tags in future. If it hadn't been an interesting challenge I wouldn't even have had a look at it.
Here's one possible split into list.hpp and main.cpp. Compile with (e.g.) just
g++ main.cpp
(plus all the compiler options you feel like adding, but which just complicate the argument here).
An alternative way of splitting is to have the class declaration in a .h file and the implementation in a .hpp file (say) that gets #include'd in the .h file (only). Take your pick. To avoid the template'd ostream operator << problem, however, I've opted here to put its definition within the class declaration. There are probably other ways.
And, yeah, I've ended up with "using namespace std;" inside a header file - so expect the full wrath of the forum on my back.