Friend-Funktionen einer Klassenvorlage

8

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.

%Vor%

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.

%Vor%

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?

    
Adrian McCarthy 14.03.2011, 19:34
quelle

3 Antworten

5

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.

    
Steve Jessop 14.03.2011, 19:46
quelle
2

Ich mag Option 1 am besten:

%Vor%

Dann ist die Funktionalität sicher in der Klasse enthalten, aber Sie stellen aus praktischen Gründen eine Wrapper-Funktion zur Verfügung.

    
Tim 14.03.2011 19:46
quelle
1

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.

    
Bo Persson 14.03.2011 19:48
quelle