( Обновление : вот полностью протестированная версия для http://ideone.com/3KGU4. Для Дополнительный вопрос , см. http://ideone.com/w0dLo)
Существует разница междуобычные перегруженные функции и функции шаблонов. Например, без ссылки на шаблоны разработчик может объявить:
void f(int x);
void f(char *x);
В качестве альтернативы разработчик может использовать шаблоны,
template <class T> void f(T x);
Основное различие междуОни заключаются в том, что с обычными функциями вы должны заранее выбрать фиксированный набор разрешенных параметров и обеспечить реализацию для каждого из них. С помощью шаблонов вы можете быть более гибкими.
Позже в вашей программе,ясно, что вы хотите, чтобы a
была функцией шаблона, а не просто (перегруженной) обычной функцией. Но когда компилятор впервые видит упоминание a
(вокруг строки 10), он выглядит так, как будто он объявляет обычную функциюЧтобы решить эту проблему, вы должны сделать два шага. Вы должны как можно скорее объявить, что a
является функцией шаблона, поэтому ваша первая строкадолжно быть:
template <typename T> int a(T& x);
Тогда вы должны объявить соответствующую дружбу.Если T
равно int
, то a
принимает параметр test<int>&
, а не int&
.Поэтому две строки друзей следует заменить на:
friend int a<test<T> >( test<T> & x); // around line 10
friend int a<test<int> >( test<int> & x); // around line 27
, а специализация a
должна быть:
template <>
int a< test<int> >(test<int>& ) // around line 30
Дополнительный вопрос
Используйте ostream
вместо ofstream
(или включите #include <fstream>
, если вы будете выводить только файлы, а не cout
).В моем ответе operator <<
- это не шаблон, а обычная перегруженная функция.Я не уверен, что возможно иметь operator<<
в качестве шаблона.Также я определил оператора в том месте, где он объявлен и объявлен как друг.Если честно, я думаю, что есть и другие, может быть, и более эффективные способы, но у меня это сработало.