Ich habe eine Klassenvorlage Foo<T>
.
Ich möchte eine Nichtmitgliedsfunktion Bar
implementieren, die zwei Foo
s benötigt und eine Foo
zurückgibt. Ich möchte, dass Bar
kein Mitglied ist, da es für Anrufer natürlicher ist, Bar(f1, f2)
als f1.Bar(f2)
zu schreiben. Ich möchte auch, dass Bar
inline
ist, weil die Berechnung trivial und häufig ist.
Der Trick ist Bar
benötigt Zugriff auf private Daten von Foo
. Ich würde lieber keinen Zugriff auf die privaten Daten haben - es gibt keinen guten Grund, die privaten Daten den Benutzern zugänglich zu machen. Daher möchte ich Bar
zu einem Freund von Foo
machen.
Hier komme ich in Schwierigkeiten. Der Compiler beschwert sich:
Der Inline-Spezifizierer kann nicht verwendet werden, wenn sich eine Friend-Deklaration auf eine Spezialisierung einer Funktionsvorlage bezieht.
Wird diese Regel vom Standard auferlegt oder ist sie spezifisch für MSVC ++?
Folgendes habe ich versucht:
Machen Sie Bar
zu einer const public member-Funktion und deklarieren Sie dann eine Nichtmitgliedsversion, die einfach lhs.Bar(rhs)
zurückgibt. Dies scheint die am wenigsten hacky Lösung.
Entfernen Sie den inline
-Hinweis, da Sie wissen, dass der Compiler ungeachtet des Hinweises über das Inlining entscheiden wird. Stört das dann die Ein-Definition-Regel? Es muss immer noch in einer Header-Datei definiert werden, da es sich um eine Funktionsvorlage handelt.
Deklarieren Sie die Elementfunktion mit einem Dummy-Vorlagentyp:
%Vor%Ich bin nicht ganz sicher, warum das funktioniert, aber es erfüllt den Compiler.
Gibt es eine bessere Lösung?
Wenn die Berechnung trivial ist, würde ich schreiben:
%Vor%Das fällt dem ODR nicht an - es ist eine Inline-Funktion mit externer Verknüpfung (3.2 / 5 schließt dies aus dem ODR aus, wenn die Definitionen identisch sind, 7.1.2 / 3 besagt, dass es inline ist).
> Dies definiert jedoch keine Funktionsvorlage Bar<T>
, sondern definiert nur eine Gruppe von Funktionsüberladungen für Bar
. Es kann einen Grund geben, der in der Frage nicht erwähnt wird, dass dies für Sie nicht funktioniert, weil Sie die Vorlage tatsächlich benötigen.
Bar ist eine Vorlage, also muss es auch eine Vorlage in der Friend-Deklaration sein.
Sie müssen nicht unbedingt einen Dummy-Parameter verwenden, sondern könnten stattdessen
verwenden %Vor%Sie können hier T nicht als Vorlagenparameter verwenden, da bereits ein äußerer T-Bereich vorhanden ist.
Tags und Links c++ non-member-functions function-templates friend