friend function & template

Started by
4 comments, last by Julian90 16 years, 10 months ago
I write some codes like this:

template<class T>
class test
{

	vector<int> v;
public:
	test()
		:v(10, 1)
	{}

	friend void show_test(test<T>&);
};

template<class T>
void show_test(test<T>& t)//friend function of test
{
	for(unsigned short i = 0; i < t.v.size(); ++i)
		cout << t.v << " ";
	cout << endl;
}

void demo_test()
{
	test<int> t;
	
	show_test(t);
}

int main()
{
	demo_test();

	return 0;
}

But the compiler always pops: Linking... cpptest.obj : error LNK2001: unresolved external symbol "void __cdecl show_test(class test<int> &)" (?show_test@@YAXAAV?$test@H@@@Z) what's wrong here?
Advertisement
You need to tell the compiler that the friend function is a template in the declaration. You can do this by appending empty <> brackets to the name like this:
friend void show_test<>(test<T>&);

The problem lies in that friend templates require explicit statement of the fact they are templates. Hence the following (with some additional comments :) )

// Don't forget to include headers so we can reproduce the example!#include <vector>#include <iostream>using namespace std; // Blehtemplate<class T>class test{	vector<int> v;public:	test() : v(10,1) {}	// Note the additional syntax making the template statement explicit	template <typename T> friend void show_test(test<T>&);};// Firstly this function shouldn't be a free function; it should be a "Report" member function of testtemplate<class T>void show_test(test<T>& t){	// Firstly tidying up the loop the way you wrote it	// How do you know "i" is an unsigned short?	for(unsigned short i = 0; i < t.v.size(); ++i)	// We are assuming v will be a vector<int>, what if you change the test class and forget to change this?	// Take advantage of the nested typedefs 	// Note that this is a good illustration of why friendship is the strongest relationship classes can have to each other:	// for(vector<int>::size_type i = 0; i < t.v.size(); ++i)		cout << t.v << " ";	cout << endl;	// And this is how I would do it, which makes life a lot easier!	// However, we are still using the int template variable explicitly - friendship, bleh	copy(t.v.begin(), t.v.end(), ostream_iterator<int>(cout, " "));	cout << endl;}int main(){	test<int> t;	show_test(t);	// So sue me, I used system("pause")	system("pause");	return 0;}// The class we could have had!// I am assuming here that the container should have been of T and not int; otherwise why template?template<class T>class test2{	vector<T> v;public:	test2() : v(10,1) {}	void Report()	{		copy(v.begin(), v.end(), ostream_iterator<T>(cout, " "));		cout << endl;	}};
Hollower, I am afraid that you suggestion doesn't work. Maybe it's compiler issue(My compiler is vc2005). Anyway, thanks a lot!

Also, special thanks to you, JimPrice! Especially your additional comments. Now everything is done. :)
I also found another solution which uses the template <class ...> variant here

Crafter 2D: the open source 2D game framework

?Github: https://github.com/crafter2d/crafter2d
Twitter: [twitter]crafter_2d[/twitter]

Quote:I also found another solution which uses the template <class ...> variant here


The two 'solutions' are identicle. In the context of a template class and typename both mean the same thing, that the template paramater is a type :). (exception: template template paramaters)

This topic is closed to new replies.

Advertisement