Ich hatte mit dem Problem in this question beschrieben (Erklären einer Vorlage Funktion als Freund einer Vorlage Klasse), und ich glaube, die zweite Antwort ist was ich tun will (forward deklarieren Sie die Vorlage Funktion, dann benennen Sie eine Spezialisierung als Freund). Ich habe eine Frage zu, ob eine etwas andere Lösung tatsächlich richtig ist oder passiert einfach in Visual C++ arbeiten 2008Vorlage Freund Funktion einer Vorlage Klasse
Prüfregeln ist:
#include <iostream>
// forward declarations
template <typename T>
class test;
template <typename T>
std::ostream& operator<<(std::ostream &out, const test<T> &t);
template <typename T>
class test {
friend std::ostream& operator<< <T>(std::ostream &out, const test<T> &t);
// alternative friend declaration
// template <typename U>
// friend std::ostream& operator<<(std::ostream &out, const test<T> &t);
// rest of class
};
template <typename T>
std::ostream& operator<<(std::ostream &out, const test<T> &t) {
// output function defined here
}
Zuerst eine seltsame Sache, die ich fand, war, dass, wenn ich ändern die Vorwärtsdeklaration von operator<<
, so dass es nicht übereinstimmt (zum Beispiel std::ostream& operator<<(std::ostream &out, int fake);
, alles kompiliert noch und funktioniert einwandfrei (um klar zu sein, muss ich eine solche Funktion nicht definieren, nur deklarieren). Wie in der linked-to-Frage, das Entfernen der Forward-Deklaration verursacht ein Problem, da der Compiler zu denken scheint, dass ich ein Datenmember statt einer Friend-Funktion deklariere. Ich bin ziemlich sicher, dass dieses Verhalten ist ein Visual C++ 2008 Fehler.
Das interessante Ding ist, wenn ich die Vorwärtsdeklarationen entferne und die alternative Freunddeklaration im Code oben verwende. Beachten Sie, dass der Vorlagenparameter U
nicht in der folgenden Signatur angezeigt wird. Diese Methode kompiliert und funktioniert auch korrekt (ohne etwas anderes zu ändern). Meine Frage ist, ob dies dem Standard oder einer Idiosynkrasie von Visual C++ 2008 entspricht (ich konnte in meinen Nachschlagewerken keine gute Antwort finden).
Beachten Sie, dass, während ein Freund Erklärung template <typename U> friend ... const test<U> &t);
auch funktioniert, das gibt tatsächlich jede Instanz des Betreibers friend
Zugriff auf jede Instanz von test
, während das, was ich will, ist, dass die privaten Mitglieder test<T>
nur von operator<< <T>
zugänglich sein sollte. Ich testete dies, indem ich eine test<int>
innerhalb der operator<<
instanziieren und auf ein privates Mitglied zugreife; Dies sollte einen Kompilierfehler verursachen, wenn ich versuche, eine test<double>
auszugeben.
Synopsis: Das Entfernen der Forward-Deklarationen und das Wechseln zu der alternativen Friend-Deklaration in dem obigen Code scheint dasselbe Ergebnis (in Visual C++ 2008) zu produzieren - ist dieser Code tatsächlich richtig?
UPDATE: Jede der oben genannten Änderungen am Code funktionieren nicht unter gcc, also vermute ich, dass dies Fehler oder "Features" im Visual C++ - Compiler sind. Trotzdem würde ich gerne Einsichten von Leuten, die mit dem Standard vertraut sind, schätzen.
Übrigens habe ich herausgefunden, dass das Hinzufügen von 'namespace std;' vor der Klassendeklaration die Notwendigkeit für die Forward-Deklarationen entfernt, was ich vermute, ist ein Nebeneffekt des (möglichen) Compiler-Bugs. –
Laut meinem Kommentar - können Sie explizit die Beispiele (einschließlich Instanziierung), die Sie sagen, arbeiten? Verbal ist es ziemlich schwer zu verstehen, was Sie für jedes Beispiel meinen. –