Ответ 1
Клэнг здесь верен. Функции Friend, определенные внутри классов, могут быть найдены только с использованием зависимого от аргументов поиска по их аргументам, а не обычным поиском. Поскольку Print
не является связанной областью для Object
, operator<<
не следует искать. Частичная цитата из Стандарта:
7.3.1.2 Определения членов пространства имен [namespace.memdef]
3 Каждое имя, впервые объявленное в пространстве имен, является членом этого Пространство имен. Если объявление друга в нелокальном классе сначала объявляет класс, функция, шаблон шаблона или шаблон функции97 друг член самого внутреннего охватывающего пространства имен. Объявление друга само по себе не делает имя видимым для неквалифицированного поиска (3.4.1) или квалифицированный поиск (3.4.3). [Примечание: имя друга будет видимый в своем пространстве имен, если соответствующая декларация предоставляется в пространство имен (до или после предоставления определения класса дружба). - end note] Если шаблон функции друга или функции имя, его имя может быть найдено путем поиска имени, которое учитывает функции из пространств имен и классов, связанных с типами аргументы функции (3.4.2).
Как упоминается выше, правильный способ добавления operator<<
to Object
состоит в том, чтобы определить его как глобальную функцию (используя интерфейс Object
) или как функцию friend
внутри себя (используя private
функции от Object
), а не в некотором вспомогательном классе. Смотрите также Herb Sutter old GotW column "Что в классе?"