Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > How can I declare and define a friend template function in a template class?

Reply
Thread Tools

How can I declare and define a friend template function in a template class?

 
 
=?gb2312?B?wfXquw==?=
Guest
Posts: n/a
 
      07-31-2007
Hi folks,
I am running into with such a question when I tried to declare and
define a friend template function in a template class, here is the
code snippet:

#include <iostream>
using namespace std;

template<typename T>
class Test {

friend Test<T> index(Test<T>& start, Test<T>& end, Test<T>& step);
};

template<typename T>
Test<T> index(Test<T>& start, Test<T>& end, Test<T>& step) {
cout << "This is index is working\n";
return Test<T>();
}


int main() {

Test<int> start = Test<int>();
Test<int> end = Test<int>();
Test<int> step = Test<int>();

Test<int> rslt = index(start, end, step);
}

When compiled with VC8.0, a linkage error araised:

Test.obj : error LNK2019: unresolved external symbol "class TVEC<int>
__cdecl index(class TVEC<int> &,class TVEC<int> &,class TVEC<int>
&)" (?index@@YA?AV?$TVEC@H@@AAV1@00@Z) referenced in function _main

 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      07-31-2007
Αυκ» wrote:
> Hi folks,
> I am running into with such a question when I tried to declare and
> define a friend template function in a template class, here is the
> code snippet:
>
> #include <iostream>
> using namespace std;
>
> template<typename T>
> class Test {
>
> friend Test<T> index(Test<T>& start, Test<T>& end, Test<T>& step);


Since 'index' is a template, it has to be declared at the namespace level
before it's declared here. Otherwise, this friend declaration refers to
a non-template function.

Take the declaration of 'index' from below (not the whole definition)
and place it before the template definition. That will require the
template itself to be *declared* before it, as well. I know, I know,
it's a PITA, but that's what is required.

> };
>
> template<typename T>
> Test<T> index(Test<T>& start, Test<T>& end, Test<T>& step) {
> cout << "This is index is working\n";
> return Test<T>();
> }
>
>
> int main() {
>
> Test<int> start = Test<int>();
> Test<int> end = Test<int>();
> Test<int> step = Test<int>();
>
> Test<int> rslt = index(start, end, step);
> }
>
> When compiled with VC8.0, a linkage error araised:
>
> Test.obj : error LNK2019: unresolved external symbol "class TVEC<int>
> __cdecl index(class TVEC<int> &,class TVEC<int> &,class TVEC<int>
> &)" (?index@@YA?AV?$TVEC@H@@AAV1@00@Z) referenced in function _main


This is what your code should look like (I think):

#include <iostream>
using namespace std;

template<typename T> class Test;

template<typename T>
Test<T> index(Test<T>& start, Test<T>& end, Test<T>& step);

template<typename T>
class Test {
... // as before


V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


 
Reply With Quote
 
 
 
 
=?gb2312?B?wfXquw==?=
Guest
Posts: n/a
 
      07-31-2007
First, thank you for your informative tips, I rewrite my code snippet,
here it is:

#include <iostream>
using namespace std;

template<typename T>
class Test;

template<typename T>
Test<T> index(T start, T end, T step);

template<typename T>
class Test {
public:
friend Test<T> index(T start, T end, T step);
};

template<typename T>
Test<T> index(T start, T end, T step) {
cout << "This is index is working\n";
return Test<T>();
}

int main() {

int start;
int end;
int step;

index(start, end, step);
}

It's the same as you think it is supposed to be, no problem with
compling and linking, but at runtime, a error is raised.

 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      07-31-2007
Αυκ» wrote:
> First, thank you for your informative tips, I rewrite my code snippet,
> here it is:
>
> #include <iostream>
> using namespace std;
>
> template<typename T>
> class Test;
>
> template<typename T>
> Test<T> index(T start, T end, T step);
>
> template<typename T>
> class Test {
> public:
> friend Test<T> index(T start, T end, T step);
> };
>
> template<typename T>
> Test<T> index(T start, T end, T step) {
> cout << "This is index is working\n";
> return Test<T>();
> }
>
> int main() {
>
> int start;
> int end;
> int step;
>
> index(start, end, step);
> }
>
> It's the same as you think it is supposed to be, no problem with
> compling and linking, but at runtime, a error is raised.


What error do *you* get?

You're passing 'start', 'end', 'step' into the function _without_
_giving them any value_. The lvalue-to-rvalue conversion required
for argument passing causes the program to have *undefined behaviour*.

Try initialising all your variables. Or just call

index(1, 2, 3);

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


 
Reply With Quote
 
=?gb2312?B?wfXquw==?=
Guest
Posts: n/a
 
      07-31-2007
Forget about the runtime error, it's because I used 3 variables before
I define them, sorry about that, it's OK when I initialize them. But a
new linkage error show itself when I tried to assign the return value
of index to another Test<T> object, here is the code snippet:

#include <iostream>
using namespace std;

template<typename T>
class Test;

template<typename T>
Test<T> index(T start, T end, T step) {
cout << "This is index is working\n";
return Test<T>();
}

template<typename T>
class Test {
public:
friend Test<T> index(T start, T end, T step);

};


int main() {

int start = 1;
int end = 32;
int step = 1;

Test<int> rslt = index(start, end, step);
}

The error is:

Test.obj : error LNK2019: unresolved external symbol "class Test<int>
__cdecl index(int,int,int)" (?index@@YA?AV?$Test@H@@HHH@Z) referenced
in function _main

 
Reply With Quote
 
hurcan solter
Guest
Posts: n/a
 
      07-31-2007
should be;


template<typename T>
class Test {
public:
template<typename T> //look here
friend Test<T> index(T start, T end, T step);

};



 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      07-31-2007
hurcan solter wrote:
> should be;
>
>
> template<typename T>
> class Test {
> public:
> template<typename T> //look here
> friend Test<T> index(T start, T end, T step);
>
> };


You can't redefine 'T' here, I think. If you only wanted to make
the 'index<T>' a friend (instantiated on the same 'T' as the class
'Test'), then a pair of angle brackets is in order (I missed that
in my post:

template<typename T>
class Test {
public:
friend Test<T> index<>(T start, T end, T step);
// ^^^^
};

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


 
Reply With Quote
 
hurcan solter
Guest
Posts: n/a
 
      07-31-2007

> You can't redefine 'T' here, I think. If you only wanted to make
> the 'index<T>' a friend (instantiated on the same 'T' as the class
> 'Test'), then a pair of angle brackets is in order (I missed that
> in my post:
>
> template<typename T>
> class Test {
> public:
> friend Test<T> index<>(T start, T end, T step);
> // ^^^^
> };
>

yes you can. it's so called friend template, in that case,all
instantiantions of the
template is the friend of class Test.Not that it's useful in this case
though, so yours
is the probably way to go.

 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      08-01-2007
hurcan solter wrote:
>> You can't redefine 'T' here, I think. If you only wanted to make
>> the 'index<T>' a friend (instantiated on the same 'T' as the class
>> 'Test'), then a pair of angle brackets is in order (I missed that
>> in my post:
>>
>> template<typename T>
>> class Test {
>> public:
>> friend Test<T> index<>(T start, T end, T step);
>> // ^^^^
>> };
>>

> yes you can. it's so called friend template, in that case,all
> instantiantions of the
> template is the friend of class Test.Not that it's useful in this case
> though, so yours
> is the probably way to go.


I repeat, the name 'T' shall not be redeclared in the definition of
'Test' for any other purpose. Try this:

template<class T> class A {
A(T) {}
template<class T> friend void foo(T t);
// template<class U> friend void foo(U u);
};

template<class T> void foo(T t)
{
A<A<T> > aat(A<int>(42));
}

int main()
{
foo(0);
}

Then, after it fails, comment the 'foo(T t)' declaration in the
class template, and uncomment the 'foo(U u)' declaration and try
again.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


 
Reply With Quote
 
Guest
Posts: n/a
 
      08-01-2007
Hi folks,

Thanks for your informative tips, both of your answers can solve my
problem successfully. But I have a question coming into my mind:

If there is any difference between:

template<typename T>
class Test {
friend Test<T> index<>(T, T, T);
// ^^^
};

and

class Test {
friend Test<T> index<T>(T, T, T);
// ^^^
};

I know you've explained it, but how can I prove that they are indeed
different, thank you.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
How to declare a friend function of a template class? Rui Maciel C++ 11 07-13-2010 06:08 PM
Declare a Friend function which is a template member function of adifferent class getrakesh@gmail.com C++ 2 02-26-2008 11:32 AM
forward declare member function so that it can be friend function yancheng.cheok@gmail.com C++ 1 11-09-2006 11:30 AM
how to declare a friend function that can access two class freegnu C++ 2 10-23-2006 09:28 AM



Advertisments