Argument dependent lookup for friend functions
Asked Answered
B

1

8

Consider the following:

namespace N {
    struct A { };

    struct B {
        B() { }
        B(A const&) { }
        friend void f(B const& ) { }
    };
}

int main() {
    f(N::B{}); // ok
    f(N::A{}); // error
}

In the first case, the case succeeds - we consider the associated namespaces of N::B and find N::f(B const&). Great.

The second case fails. Why? According to [namespace.memdef]:

If a friend declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace. [...] 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).

The associated namespace of N::A is N, of which f is a member, so why is it not found by lookup?

Boneset answered 16/3, 2016 at 0:58 Comment(0)
L
9

It's because f is not declared in an associated class. B is an associated class when the argument is of type B, but not when the argument is of type A.

I quote from [basic.lookup.argdep]/4, emphasis mine:

When considering an associated namespace, the lookup is the same as the lookup performed when the associated namespace is used as a qualifier (3.4.3.2) except that:

— Any using-directives in the associated namespace are ignored.

— Any namespace-scope friend functions or friend function templates declared in associated classes are visible within their respective namespaces even if they are not visible during an ordinary lookup (11.3).

— All names except those of (possibly overloaded) functions and function templates are ignored.

Lebna answered 16/3, 2016 at 1:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.