Reputation: 39881
I have written the following code:
#include <iostream>
using namespace std;
template <class T>
class AA
{
T a;
public:
AA()
{
a = 7;
}
friend void print(const AA<T> & z);
};
template <class T>
void print(const AA<T> & z)
{
cout<<"Print: "<<z.a<<endl;
}
void main()
{
AA<int> a;
print<int>(a);
}
And getting the following error:
error C2248: 'AA<T>::a' : cannot access private member declared in class 'AA<T>'
1> with
1> [
1> T=int
1> ]
1> c:\users\narek\documents\visual studio 2008\projects\aaa\aaa\a.cpp(7) : see declaration of 'AA<T>::a'
1> with
1> [
1> T=int
1> ]
1> c:\users\narek\documents\visual studio 2008\projects\aaa\aaa\a.cpp(30) : see reference to function template instantiation 'void print<int>(const AA<T> &)' being compiled
1> with
1> [
1> T=int
1> ]
What's wrong?
P.S. I am using Visual Studio 2008.
Upvotes: 3
Views: 884
Reputation: 18326
The problem is that when you do something like
template<class T>
class AA {friend void print(const AA<T>&);};
and you instantiate AA
with like this
AA<int> a;
the friend declaration will be instantiated like
friend void print(const AA<int>&);
which is a non-template function! This means the compiler will not match the friend declaration with your print
function.
The solution is basically to declare print
before AA
and explicitly tell the compiler that your friend declaration is talking about a template function. Like this:
#include <iostream>
using namespace std;
//forward declare AA because print needs it
template<class T>
class AA;
//declare print before AA to make the friend declaration
//match with this function
template<class T>
void print(const AA<T> & z);
template <class T>
class AA
{
//the <> is needed to make sure the compiler knows we're
//dealing with a template function here
friend void print<>(const AA<T> & z);
public:
AA() {a = 7;}
private:
T a;
};
//implement print
template<class T>
void print(const AA<T> & z)
{
cout<<"Print: "<<z.a<<endl;
}
int main()
{
AA<int> a;
print(a);
}
It is interesting to see what happens if you do not add the <>
in the friend declaration. You will get a linker error. Why? Well, because the compiler cannot match the friend declaration with your template print
function, it will implicitly assume a function with prototype
void print(const AA<int>&);
exists. Since I didn't explicitly provide a template parameter to the call to print
(which isn't necessary because the compiler should be able to deduce this), the compiler will match this call with the function declared as friend. This function is nowhere implemented, hence the linker error.
Upvotes: 3
Reputation: 4659
You can also define friend function inside class definition:
#include <iostream>
using namespace std;
template <class T>
class AA
{
T a;
public:
AA()
{
a = 7;
}
friend void print(const AA<T> &z)
{
cout<<"Print: "<<z.a<<endl;
}
};
int main()
{
AA<int> a;
print(a);
}
Upvotes: 1