Проблема в том, что когда вы делаете что-то вроде
template<class T>
class AA {friend void print(const AA<T>&);};
и вы создаете AA
с таким
AA<int> a;
, объявление друга будет создаваться как
friend void print(const AA<int>&);
это не шаблонная функция!Это означает, что компилятор не будет сопоставлять объявление друга с вашей функцией print
.
Решение в основном состоит в том, чтобы объявить print
перед AA
и явно сообщить компилятору, что объявление вашего друга говорит о шаблонефункция.Например:
#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);
}
Интересно посмотреть, что произойдет, если вы не добавите <>
в объявление друга.Вы получите ошибку компоновщика.Зачем?Ну, поскольку компилятор не может сопоставить объявление друга с вашей функцией шаблона print
, он неявно предполагает, что существует функция с прототипом
void print(const AA<int>&);
.Так как я не предоставил явно параметр шаблона для вызова print
(что не обязательно, потому что компилятор должен уметь это выводить), компилятор сопоставит этот вызов с функцией, объявленной как друг.Эта функция нигде не реализована, поэтому ошибка компоновщика.