Mit C ++ 11 std :: enable_if, um die Elementfunktion zu aktivieren, wenn der Vektor eine bestimmte Länge hat

8

Ich schreibe eine einfache Vektorklasse und möchte einige Member-Funktionen haben, die nur in Vektoren bestimmter Länge verfügbar sind (z. B. Kreuzprodukt für einen 3-Element-Vektor). Ich stolperte über st :: enable_if und es sieht so aus, als könnte es tun, was ich will, aber ich scheine nicht in der Lage zu sein, es richtig funktionieren zu lassen.

%Vor%

Der Code oben kompiliert und läuft korrekt, aber wenn ich die Deklaration von Vector<double,4> v4 auskommentiere, bekomme ich den folgenden Fehler beim Kompilieren:

%Vor%

Kann jemand darauf hinweisen, wo ich falsch liege?

    
rozzy 09.12.2012, 10:04
quelle

1 Antwort

8
%Vor%

PS. Warum funktioniert das so?

Die Definition der Variable v4 bewirkt eine implizite Instanziierung der Klassenvorlage Vector , die unter anderem zur impliziten Instantiierung der Deklarationen von Klassenmemberfunktionen führt (14.7.1 Implizite Instantiierung [temp .inst] # 1). Diese letztere Instantiierung führt natürlich zu einem Fehler.

Wenn wir stattdessen die Memberfunktion als Membervorlage ändern, wird an derselben Stelle die Membervorlage selbst instanziiert, und diese Instanziierung sieht mehr oder weniger wie folgt aus:

%Vor%

Dies ist eine vollständig gültige Template-Deklaration. Wir können (und können nicht) zu diesem Zeitpunkt weitere Instanziierungen durchführen.

Wenn wir jedoch versuchen, cross tatsächlich aufzurufen, ist dies zweifellos "ein Kontext, der die Definition von Membern / Funktionen benötigt", also gemäß (14.7.1 Implizite Instantiierung [temp.inst] # 2, # 3), wird die Vorlage cross (die zweite Vorlage cross , die eine Folge der Instanziierung der äußeren Klassenvorlage ist) implizit instanziiert und der std::enable_if wird Gelegenheit gegeben, ihre Arbeit zu tun. Als Randbemerkung ist dies die Situation, in der das SFINAE-Prinzip anwendbar ist.

PPS. Etwas ausführlicher, obwohl nicht direkt mit der OP-Frage verbunden, aber immer noch erwähnenswert, dass es nicht immer notwendig ist, Mitglieder als Vorlagen zu deklarieren, um mit ähnlichen Situationen umzugehen.

Es gibt Situationen, in denen ein Mitglied einer Klassenvorlage für eine gegebene Instanziierung nicht "gültig" ist, aber dennoch die Klassenvorlage instanziiert werden kann, zum Beispiel:

%Vor%

Anscheinend ist in der Instanziierung S<int> der Ausdruck *x ungültig, weil der Typ von x int ist. Dieses Programm ist jedoch korrekt. Wichtig ist, dass bei der impliziten Instanziierung nur die Deklarationen der Member instanziiert werden. Im obigen Fall bewirkt die Instanziierung S<int> , dass die Deklaration int bar() const; instanziiert wird, was eine vollständig korrekte Deklaration ist.

Natürlich, wenn wir später versuchen, die Definition von S<int>::bar zu instanziieren, wie in:

%Vor%

wir werden einen Fehler bekommen.

(Dies folgt immer noch aus den oben genannten zwei Absätzen des C ++ - Standards)

    
chill 09.12.2012, 10:20
quelle

Tags und Links