Clang is correct here. Friend functions defined inside classes can only be found using argument-dependent-lookup on their arguments, not by ordinary lookup. Because Print
is not an associated scope to Object
, the operator<<
should not be found. Partial quote from the Standard:
7.3.1.2 Namespace member definitions [namespace.memdef]
3 Every name first declared in a namespace is a member of that
namespace. If a friend declaration in a non-local class first declares
a class, function, class template or function template97 the friend is
a member of the innermost enclosing namespace. The friend declaration
does not by itself make the name visible to unqualified lookup (3.4.1)
or qualified lookup (3.4.3). [ Note: The name of the friend will be
visible in its namespace if a matching declaration is provided at
namespace scope (either before or after the class definition granting
friendship). — end note ] If a friend function or function template is
called, its name may be found by the name lookup that considers
functions from namespaces and classes associated with the types of the
function arguments (3.4.2).
As @sehe mentions, the proper way to add an operator<<
to Object
is to define it as a global function (using Object
interface) or as a friend
function inside itself (using private
functions from Object
), not in some auxiliary class. See also Herb Sutter's old GotW column "What's in a class?"