Warum stimmen C ++ - Vorlagen überein, wenn die Methode keine Überprüfung durchführt?

8

Der folgende Code wird nicht kompiliert, da struct A den Operator -- nicht unterstützt.

%Vor%

Gleiches gilt für diesen Code.

%Vor%

Warum kompiliert das (in C ++ 11)?

%Vor%

Scheint, dass das Instanziieren der Vorlage nicht automatisch unbenutzte Methoden in der Vorlage instanziiert, die von dem Typparameter für die Typüberprüfung abhängen, was bedeutet, dass die Vorlage auch dann übereinstimmt, wenn einige ihrer Methoden dies nicht tun. Es ist enttäuschend, weil ich gehofft habe, SFINAE zu verwenden, um die Anwendbarkeit verschiedener Methoden und Operatoren auf Typen zu erkennen, aber wenn die Template-Substitution erfolgreich ist, selbst wenn Aufrufe der Methoden Kompilierungsfehler wären, wird die Technik nicht funktionieren.

    
Joel Micah Donovan 17.07.2017, 17:11
quelle

1 Antwort

5

Es wurde entschieden (vom C ++ - Komitee), dass Methoden von Template-Klassen nur dann instanziiert werden, wenn sie verwendet werden.

Dies macht es einfacher, C ++ - Code auf Kosten von Hardfehlern zu schreiben, wenn sie verwendet werden.

Als Beispiel verwendet std::vector es mit std::vector::operator< ; Wenn Sie kein < aufrufen, ist das ein Fehler. Wenn Sie das tun, funktioniert der Aufruf.

Moderneres C ++ würde SFINAE dazu ermutigen, es zu deaktivieren, damit Sie erkennen können, ob < sicher ist oder nicht, aber diese Technik wurde nicht verwendet, als std::vector entworfen wurde. Sie können die Entwicklung der Verwendung dieser Technik in std::function sehen, die von gierig verbraucht fast alles in einem universellen Konstruktor zu jenem Konstruktor ging, der nur für die Überladungsauflösung in Betracht gezogen wurde, wenn es zwischen C ++ 11 und C ++ 14 funktionieren würde / p>

Wenn Sie SFINAE wollen, können Sie sich nicht auf die Codezeilen verlassen. Um die Belastung für Compiler zu verringern, müssen Compiler nur Deklarationen nicht Definitionen von Funktionen untersuchen, wenn sie SFINAE-Tests durchführen.

Ein Teil des Grundes ist, dass SFINAE auf Ausdrücke hart ist; auf ganzen Körpern ist härter. Der Compiler muss spekulativ den Hauptteil der Funktion kompilieren, den Fehler treffen und dann wieder in den Zustand "nein, nichts wurde getan" zurückkehren.

Fehler im Rumpf von Funktionen sind immer harte Fehler. Sie können dies in der aktuellen Version von C ++ nicht vermeiden.

Nun können Sie Funktionen schreiben, die entscheiden, ob Fehler auftreten oder nicht, aber keinen Fehler haben. Verwenden Sie dann ihre Körper, um festzustellen, ob anderer Code fehlerhaft ist. Zum Beispiel:

%Vor%

Sie können foo<char>() irgendwo in SFINAE verwenden, und seine true oder false -ness kann dazu führen, dass eine andere Überladungssubstitution fehlschlägt oder nicht.

Beachten Sie, dass der Fehler (falls vorhanden) immer noch außerhalb des Hauptteils einer Funktion auftritt ( foo hier).

    
Yakk 17.07.2017 17:34
quelle

Tags und Links