7

Beachten Sie Folgendes:Argument abhängige Lookup für Freund funktioniert

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 
} 

Im ersten Fall, der Fall gelingt - wir betrachten den zugehörigen Namensraum von N::B und N::f(B const&) finden. Groß.

Der zweite Fall schlägt fehl. Warum? Nach [namespace.memdef]:

Wenn eine friend Erklärung in einer nicht-lokalen Klasse zuerst eine Klasse, Funktion, Klassenvorlage oder Funktionsschablone deklariert ist der Freund ein Mitglied der innersten einschließenden Namespace. [...] Wenn eine Freundes- oder Funktionsvorlage aufgerufen wird, kann ihr Name durch die Namenssuche gefunden werden, die Funktionen aus Namespaces und Klassen berücksichtigt, die den Typen der Funktionsargumente zugeordnet sind (3.4.2).

Der zugehörige Namensraum von N::A ist N, von denen f Mitglied ist, also warum wird sie nicht durch Nachschlagen gefunden?

Antwort

8

Es ist, weil f nicht in einer zugeordneten Klasse deklariert ist. B ist eine zugeordnete Klasse, wenn das Argument vom Typ B ist, aber nicht, wenn das Argument vom Typ A ist.

Ich zitiere aus [basic.lookup.argdep]/4, Hervorhebung von dir:

Wenn ein zugehörigen Namensraum unter Berücksichtigung die Lookup ist das gleiche wie die Suche durchgeführt, wenn der zugehörige Namespace als eine verwendet wird, Qualifikationsmerkmal (3.4.3.2) mit der Ausnahme:

- Alle using-Direktiven im zugehörigen Namespace werden ignoriert.

- Alle Namespace-scope friend-Funktionen oder Freund Funktionsschablonen in zugehörigen Klassen deklariert sind sichtbar in ihren jeweiligen Namensräume, auch wenn sie während eines gewöhnlichen Lookup nicht sichtbar sind (11.3).

- Alle Namen außer den (möglicherweise überladenen) Funktionen und Funktionsvorlagen werden ignoriert.