2013-10-18 10 views
14

C++ 03 und C++ 11 hat im ersten Absatz von [temp.friend]:Freund eine Vorlage Spezialisierung ohne <>

[Bearbeitet Zitat. Erster Versuch verpassten einen zweiten Unterschied in der Formulierung]

Für eine Freund Funktionsdeklaration, die keine Template-Deklaration ist.

  1. , wenn der Name des Freundes ein qualifizierter oder unqualifizierter ist Template-id, bezieht sich die Erklärung auf eine Freund Spezialisierung einer Funktionsschablone, sonst

  2. , wenn der Name des Freundes, eine qualifizierte ID und eine passenden nichtcodierende FKT -Ion in der angegebenen Klasse oder Namensraum gefunden wird, bezieht sich die Freund Erklärung für diese Funktion, andernfalls

  3. [C++ 03:], wenn der Name des Freundes ist eine qualifizierte ID und eine passende Spezialisierung eine Funktion Vorlage wird in der angegebenen Klasse oder Namespace, der Freund Erklärung bezieht

    diese Funktion Vorlage Spezialisierung, andernfalls

    [C++ 11:] zu finden ist eine qualifizierte Nummer, wenn der Name des Freundes und und Eine passende Funktionsschablone wird in der angegebenen Klasse oder dem angegebenen Namespace gefunden. Die Friend-Deklaration bezieht sich auf die abgeleitete Spezialisierung dieser Funktionsschablone, andernfalls

  4. Der Name soll eine unqualifizierte ID sein, die eine normale (Nintemplate) Funktion deklariert (oder deklariert).

[Die Änderung in der Formulierung scheint mir, wie Klarstellung. Obwohl ich denke, dass es verschiedene Möglichkeiten geben könnte, die C++ 03-Formulierung über "eine Spezialisierung in einer Klasse oder einem Namespace zu finden" zu interpretieren.]

Ich bin neugierig auf diese dritte Kugel. Ich schrieb diesen Code zu versuchen, seine Anforderungen zu entsprechen, aber beide g ++ 4.8.1 und Klirren ++ 3.4 lehnen den Code, ob mit -std = C++ 03 oder -std = C++ 11:

template <class T> class R; 
namespace N { 
    template <class T> void test(const R<T>&); 
} 

template <class T> 
class R { 
    friend void N::test(const R<T>&); // 8 
    int m; 
}; 

template <class T> 
void N::test(const R<T>& rec) { rec.m; } 

int main() { 
    R<int> r; 
    N::test(r); 
} 

Of Natürlich, wenn ich Linie 8 zu

friend void N::test<>(const R<T>&); 

die erste Kugel ändert gilt und das Programm akzeptiert wird. g ++ gibt eine hilfreiche Warnung aus, die besagt, dass der Freund "eine Nicht-Template-Funktion deklariert" und vorschlägt, dass ich genau das tun möchte. Der Code würde wahrscheinlich mehr Stilpunkte für Klarheit und Sicherheit bekommen.

Aber sollte nicht der obige Code von der dritten Kugel abgedeckt und gültig sein? Die Friend-Deklaration ist keine Template-Deklaration und verwendet eine qualifizierte ID, die keine Template-ID als Name ist. Und es gibt keine Nintemplate-Funktionsdeklaration für das zweite Aufzählungszeichen.

Ist das nur ein Compilerfehler, der beiden gemeinsam ist? Oder habe ich etwas missverstanden, und wenn ja, gibt es ein Beispiel für ein Programm, das diese dritte Kugel vorführt?

+0

+1 Interessant. Ich vermute, dass '<>' Teil des "Namens des Freundes" ist. –

+0

@JohnDibling: * qualifizierte-ID * enthält unter anderem * Template-ID *, also ja, 'f <>' ist eine * qualifizierte-ID * insgesamt. –

+0

@JohnDibling Ja, die Token '<' and '>' sind Teil der _template-id_. Ein _name_ kann ein _identifier_, _operator-function-id_, _literal-operator-id_, _conversion-function-id_ oder _template-id_ [basic/4] sein. – aschepler

Antwort

0

Ich denke, dass <> ist eine Voraussetzung für den Abzug stattfinden, da von 14.8.2.6,

In einer Erklärung, deren declarator-ID bezieht sich auf eine Spezialisierung einer Funktionsvorlage, Template-Argument Abzug wird durchgeführt, um die Spezialisierung zu identifizieren, auf die sich die Deklaration bezieht. Konkret geschieht dies für explizite Instanziierungen (14.7.2), explizite Spezialisierungen (14.7.3) und bestimmte Freundschaftsdeklarationen (14.5.4).

In diesem Fall ist die Deklarator-ID keine Spezialisierung, daher findet kein Abzug statt.

+0

[temp.arg.explicit]/3 sagt "Wenn alle Template-Argumente abgeleitet werden können, können sie alle weggelassen werden; in diesem Fall kann auch die leere Template-Argumentliste' <> 'selbst weggelassen werden." Eine * Deklarator-ID * ** ist ** niemals eine Spezialisierung, es ist ein Name. ** bezieht sich ** auf eine Spezialisierung, siehe [temp.fct.spec]/1. – dyp

0

N :: Test ist eine Template-Funktion, die eine Klasse namens T übernimmt. Es braucht keine Klasse namens R<T>. Ändern Sie die Funktionen entsprechend und es wird funktionieren.

namespace N 
{ 
    template <class T> 
    void test (const T &); 
} 

template <class T> 
class R 
{ 
    friend void N::test (const R<T> &); 
    int m; 
}; 

template <class T> 
void N::test (const T & rec) { rec.m; } 

int main () 
{ 
    R<int> r; 
    N::test (r); 
} 
+0

Könnten Sie bitte erläutern? Warum gilt [temp.friend]/3 nicht? – dyp

+0

Der Abzug funktioniert gut, z.B. für eine explizite Instantiierung wie 'template void N :: test (const R &);' (im globalen Namespace; behalte 'template void test (const R &);'). – dyp

+0

Sowohl g ++ 4.9 als auch clang ++ 3.4 [lehnen Sie Ihr Programm ab] (http://coliru.stacked-crooked.com/a/667de82019cb0932) (sogar clang ++ 3.6). Welchen Compiler hast du benutzt? Es ist auch ähnlich zu [was ich bemerkt habe] (http://coliru.stacked-crooked.com/a/259d11dc3d3719ee) [vor einem Jahr] (http://stackoverflow.com/questions/19459283/friend-a -Template-Spezialisierung-ohne # comment28876623_19459283). – dyp

1

in Zeile // 8, modifizierten Code wie: friend void N::test< R<T> >(R<T>&); richtig zu.

friend void N::test<R<T>>(const R<T>&);//one type is friend with one type #1 
friend void N::test<>(const R<T>&);// one type is friend with one type #2 

Ich verwende einen Code Beweis dafür, dass 1 # # gleich 2 ist

Endlich versuche ich Ihre Frage .Ich bin zu beantworten nicht sicher, das ist richtig.

friend void N::test(const R<T>&); 

wenn die Klasse R Instanziieren ist R<T> ein bekannter Typ. Allerdings ist die Funktion

als Freund Funktion deklariert ist und wirklich keine Funktion Vorlage instanziiert, dann ist die

friend-Funktion ist eine Funktion, die nicht existiert. Aus der Sicht der Grammatik, die

Compiler wird Sie auffordern, dass es sich um eine Funktion eher als eine Vorlage In diesem Ort

N::test (r); 

ist die Funktion instanziiert wird, aber der Compiler mit einem

nicht überein

Freund vor der Deklaration in R-Klasse, weil Sie nicht als Vorlage in R

Klasse deklarieren, deklarieren Sie einfach eine Funktion.

Verwandte Themen