Dear all,
I'm creating a set of functions to handle stl vectors. Some are useful for achieving my goals. I'm coding some other just for fun. But after some coding I see I cannot compile them propperly.

One example would be a vector print function which prints all the elements of a vector of an arbitrary type.

--- vecTools.h---
template <typename T>
void printVector (T &v1);

--- vecTools.cpp---
#include "vecTools.h"

template <typename T >
void printVector ( T &v1){
	cout<<"[ ";
	for (unsigned int i =0; i < v1.size(); i++){
		cout<<v1[i]<<", ";
	}
	cout<<"] \n";
}

The answer of the g++ compiler is as follows:

../src/Tools/Test/main.cpp:39: undefined reference to `void printVector<DummyObject>(std::vector<DummyObject, std::allocator<DummyObject> >&)'
collect2: ld returned 1 exit status
make: *** [core_iteration1] Error 1

Do you know how can one fix this? Maybe it's impossible?

Many thanks!!
Víctor

Btw, my first attempt was like this. It doesn't work either:

--- vecTools.h---
template <typename T>
void printVector (vector<T> &v1);

--- vecTools.cpp---
#include "vecTools.h"

template <typename T >
void printVector ( vector<T> &v1){
	cout<<"[ ";
	for (unsigned int i =0; i < v1.size(); i++){
		cout<<v1[i]<<", ";
	}
	cout<<"] \n";
}

with the resulting error message:

../src/Tools/Test/main.cpp:39: undefined reference to `void printVector<DummyObject>(std::vector<DummyObject, std::allocator<DummyObject> >&)'

And I call the function into main like this:

class DummyObject{
	public:
		DummyObject(){ n = 0;}
		DummyObject(int n){ this->n = n;}
		DummyObject(const DummyObject& d){ this->n = d.n;}
		~DummyObject(){ }

	private:
		int n;
};

vector<DummyObject> norm_vect;

void testInit(){
	cout<<"------------------"<<endl<<"Initializing tests"<<endl<<"------------------"<<endl;
	norm_vect.push_back(DummyObject(4));
	norm_vect.push_back(DummyObject(3));
	norm_vect.push_back(DummyObject(8));
	norm_vect.push_back(DummyObject(5));
	norm_vect.push_back(DummyObject(9));
	norm_vect.push_back(DummyObject(1));
	norm_vect.push_back(DummyObject(2));
	norm_vect.push_back(DummyObject(0));
	norm_vect.push_back(DummyObject(7));
	norm_vect.push_back(DummyObject(6));


	printVector(norm_vect);
}

int main(int argc, char *argv[])
{
	
	testInit();

	return EXIT_SUCCESS;
}

You should pass the vector by reference to the Init function if you want it to recieve values. Displaying it you have to pass it be value.

template<typename T> void testInit(vector<T>&);
template <typename T> void Display(vector<T>);

The vector is defined as a global variable (norm_vect) so I don't have to pass it as parameter to the driver function (testInit).

I'm afraid your solution doesn't work (but why do you think It should work? I'm just curious). I tried:

template <typename T>
void printVector (vector<T> v1);

template <typename T >
void printVector ( vector<T> v1){
	cout<<"[ ";
	for (unsigned int i =0; i < v1.size(); i++){
		cout<<v1[i]<<", ";
	}
	cout<<"] \n";
}

Thanks for your answer anyway,

Víctor

Sorry .. i meant to say that you don't have to pass the vector as reference in order to print it's members.
Try appending an actual value to the vector because a constructor deos not have a return type from what i know.

How do you build your project?

This is simply an error with the way the code is ordered. You're placing the declaration and definition of a template function in 2 different files. When you do that, and vecTools.cpp is compiled, the compiler knows nothing of typename T, and so simply optimizes it away. The way to fix it is to either move the definition into the header file, or to add relevant declarations in the .cpp file, i.e.

template void printVector(vector<float> v1);
template void printVector(vector<int> v1);
... and so on

Then the function will be usable for whatever types you add such declarations for. I'd personally recommend the 1st option, which is to simply move the definition to the header file, as part of the declaration. If you get multiple definition errors, which you should not, you can enclose the code in a #ifdef #endif block

The problem is you separate the definition of printVector. Your compiler can't handle
defining a template function somewhere else than its declared file. So do this instead.

//myTools.h
template<class Iterator>
static void print(Iterator begin, Iterator end){
 while(begin != end){ cout << *begin++ << " "; };
}

Better yet, use your own namespace.

namespace MyTools{

template<class Iterator>
 void print(Iterator begin, Iterator end){
   while(begin != end){ cout << *begin++ << " "; };
 } 

 template<typename T>
 print(T arg){ cout << arg ; }
 
 template<class Iterator>
 println(T arg){ cout << arg << endl; }
 
 //more tools
}

Then you can use it like this :

#include "MyTools.h"
int main(){
 MyTools::print("hello");
 vector<int> vec(4,4);
 MyTools::print(vec.begin(),vec.end());
 
 using namespace MyTools;
 print("world");
 print(vec.begin(),vec.end());

 return 0;
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.