Подтвердить что ты не робот

Перегрузка оператора друга << для шаблона класса

Я пытаюсь перегрузить оператор < < как друга к шаблону класса 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;
};

Я не был уверен, что делать с предупреждением рекомендации, кроме этого, может быть, мне нужно помещать где-нибудь в декларацию друга. Кто-нибудь знает правильный синтаксис для этого? Спасибо.

4b9b3361

Ответ 1

Вы объявляете оператор < < как возвращение ostream &, но в методе возврата нет вообще никакого метода. Должно быть:

template <class T, class U>
ostream& operator<<(ostream& out, Pair<T,U>& v)
{
    return out << v.val1 << " " << v.val2;
}

Кроме этого, у меня нет проблем или предупреждений, компилирующих ваш код в Visual Studio 2008 с предупреждениями на уровне 4. О, есть классические ошибки компоновщика, но это легко обойти, переместив определение функции шаблона в объявление класса, как описано в часто задаваемые вопросы по С++.

Мой тестовый код:

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

Ответ 2

Вы хотите сделать один экземпляр (называемый "специализация" в общих терминах) этого шаблона другом. Вы делаете это следующим образом.

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

Ответ 3

Простая встроенная версия:

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