Перегрузка оператора друга << для шаблона класса
Я пытаюсь перегрузить оператор << как друга в шаблоне класса Pair, но получаю предупреждение компилятора, говорящее
friend declaration std::ostream& operator<<(ostream& out, Pair<T,U>& v) declares a non template function
для этого кода:
friend ostream& operator<<(ostream&, Pair<T,U>&);
это дает второе предупреждение в качестве рекомендации, говоря
if this is not what you intended, make sure the function template has already been declared and add <> after the function name here
Вот определение функции
template <class T, class U>
ostream& operator<<(ostream& out, Pair<T,U>& v)
{
out << v.val1 << " " << v.val2;
}
и вот весь класс.
template <class T, class U>
class Pair{
public:
Pair(T v1, U v2) : val1(v1), val2(v2){}
~Pair(){}
Pair& operator=(const Pair&);
friend ostream& operator<<(ostream&, Pair<T,U>&);
private:
T val1;
U val2;
};
Я не был уверен, что следует извлечь из предупреждения о рекомендации, кроме того, что, возможно, я должен был указать где-нибудь в объявлении друга. Кто-нибудь знает правильный синтаксис для этого? Благодарю.
3 ответа
Вы объявляете operator<< как возвращающий ostream&, но в методе вообще нет оператора return. Должно быть:
template <class T, class U>
ostream& operator<<(ostream& out, Pair<T,U>& v)
{
return out << v.val1 << " " << v.val2;
}
Кроме этого, у меня нет проблем или предупреждений, компилирующих ваш код в Visual Studio 2008 с предупреждениями на уровне 4. О, есть классические ошибки компоновщика, но это легко обойти, перенеся определение функции шаблона в объявление класса, как объяснено в C++ FAQ.
Мой тестовый код:
#include <iostream>
using namespace std;
template <class T, class U>
class Pair{
public:
Pair(T v1, U v2) : val1(v1), val2(v2){}
~Pair(){}
Pair& operator=(const Pair&);
friend ostream& operator<<(ostream& out, Pair<T,U>& v)
{
return out << v.val1 << " " << v.val2;
}
private:
T val1;
U val2;
};
int main() {
Pair<int, int> a(3, 4);
cout << a;
}
Вы хотите сделать один экземпляр (называемый "специализация" в общих чертах) этого шаблона другом. Вы делаете это следующим образом
template <class T, class U>
class Pair{
public:
Pair(T v1, U v2) : val1(v1), val2(v2){}
~Pair(){}
Pair& operator=(const Pair&);
friend ostream& operator<< <> (ostream&, Pair<T,U>&);
private:
T val1;
U val2;
};
Поскольку компилятор знает из списка параметров, что аргументы шаблона T
а также U
Вы не должны помещать эти между <...>
так что их можно оставить пустыми. Обратите внимание, что вы должны поставить декларацию operator<<
выше Pair
шаблон, как показано ниже:
template <class T, class U> class Pair;
template <class T, class U>
ostream& operator<<(ostream& out, Pair<T,U>& v);
// now the Pair template definition...
Простая встроенная версия:
template<typename T> class HasFriend {
private:
T item;
public:
~HasFriend() {}
HasFriend(const T &i) : item(i) {}
friend ostream& operator<<(ostream& os, const HasFriend<T>& x) {
return os << "s(" << sizeof(x) << ").op<<" << x.item << endl;
}
};
Пересмотренная версия шаблона:
template<template<typename /**/> class U, typename V>
ostream& operator<<(ostream &os, const U<V> &x) {
return os << "s(" << sizeof(x) << ").op<<" << x.item << endl;
}
template<typename T> class HasFriend {
private:
T item;
public:
~HasFriend() {}
HasFriend(const T &i) : item(i) {}
friend ostream& operator<<<>(ostream&, const HasFriend<T>&);
};