Как определить и использовать функцию Friend для класса temlate с тем же шаблоном? - PullRequest
3 голосов
/ 15 июня 2010

Я написал следующий код:

#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);
}

И получаю следующую ошибку:

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>        ]

Что не так?

PS Я использую Visual Studio 2008.

Ответы [ 2 ]

3 голосов
/ 15 июня 2010

Проблема в том, что когда вы делаете что-то вроде

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 (что не обязательно, потому что компилятор должен уметь это выводить), компилятор сопоставит этот вызов с функцией, объявленной как друг.Эта функция нигде не реализована, поэтому ошибка компоновщика.

1 голос
/ 15 июня 2010

Вы также можете определить функцию друга в определении класса:

#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);
}
...