Объявление шаблона друга с вложенным классом в качестве аргумента

C ++ FAQ предлагает руководство по написанию объявлений шаблонов друзей. Однако у меня проблема, когда один из аргументов является вложенной структурой класса шаблона, например:

template<typename T>
class MyClass;
template<typename T> QDataStream &operator<<(QDataStream &stream, const typename MyClass<T>::Node &node);

Ни одна из этих версий не работает:

template<typename T>
class MyClass
{
private:
    struct Node {};
    friend QDataStream &operator<< <>(QDataStream &stream, const Node &node);
    friend QDataStream &operator<< <>(QDataStream &stream, const MyClass::Node &node);
    friend QDataStream &operator<< <>(QDataStream &stream, const MyClass::Node &node);
    friend QDataStream &operator<< <>(QDataStream &stream, const typename MyClass<T>::Node &node);
    friend QDataStream &operator<< <>(QDataStream &stream, const typename MyClass::Node &node);
};

template<typename T>
QDataStream &operator<<(QDataStream &stream, const typename MyClass<T>::Node &node)
{
    return stream;
}

Приведенная ошибка (по MSVC 2017):

error: C2672: '<<': no matching overloaded function found

Каким будет правильный синтаксис для написания этого?

Живая демонстрация


person Resurrection    schedule 03.08.2018    source источник
comment
Прежде всего, попробуйте создать минимальный, полный и проверяемый пример, чтобы показать нам. Во-вторых, скопируйте и вставьте (как текст) выходные данные full и complete ошибки из этого MCVE.   -  person Some programmer dude    schedule 03.08.2018
comment
@Someprogrammerdude Добавлен как демо-версия на Godbolt   -  person Resurrection    schedule 03.08.2018


Ответы (1)


Этот operator<< никогда не может использоваться в качестве оператора, потому что T появляется только в невыведенном контексте. По той же причине компилятор не может вывести аргумент шаблона при попытке точно выяснить, с какой специализацией какого шаблона функции вы пытаетесь сопоставить.

Также существует небольшая проблема, заключающаяся в том, что специализация называет закрытый член Node, к которому у него нет доступа (компилятор не может понять, что объявление friend предоставляет ему такой доступ, пока он не выяснит, какая специализация названа объявлением).

Обычное исправление состоит в том, чтобы определить оператор как встроенную нешаблонную функцию внутри определения шаблона класса или извлечь Node в свой собственный шаблон класса.

person T.C.    schedule 03.08.2018