Substitution failure is not an error
# Substitution failure is not an error

Substitution failure is not an error (SFINAE) ist eine Programmiertechnik in der Programmiersprache C++. Dabei wird die Tatsache ausgenutzt, dass eine fehlgeschlagene Substitution von Template-Argumenten keinen Kompilierfehler erzeugt.

Ist beispielsweise eine Funktion mehrfach überladen und sind gewisse Kandidaten das Ergebnis der Instanziierung eines Funktionstemplates mit möglicherweise deduzierten Template-Argumenten, so wird – sofern die Substitution der Template-Argumente fehlgeschlagen ist – die Überladung aus der Menge der Kandidaten entfernt, ohne dass der Kompiliervorgang mit einem Kompilierfehler abgebrochen wird. Sind die schließlich verbliebenen Kandidaten mehrdeutig, beispielsweise weil sie dieselbe Signatur haben und sich nur durch den Rückgabewert unterscheiden, oder sind keine Kandidaten für den Funktionsaufruf mehr vorhanden, so wird dennoch wie üblich ein Kompilierfehler erzeugt.

## Beispiele

Als Standardbeispiel sei ein Konstrukt genannt, das von einem Typen T bestimmt, ob T::Type ebenfalls ein Typ ist.

Die Rückgabewerte der Tester-Funktion sind Referenzen, da in C++ bekanntlich keine Arrays zurückgegeben werden können. Der sizeof-Operator gibt beim Anwenden auf eine Referenz die Größe des referenzierten Types zurück. Beim Anwenden auf einen vermeintlichen Funktionsaufruf (also auf eine Funktion inkl. Funktionsargumente) wird die Größe des Rückgabewertes angegeben. Da die Funktion in Tat und Wahrheit nie wirklich aufgerufen wird, ist keine Funktionsdefinition vonnöten. Um die Größe des Rückgabewertes angeben zu können, muss zuerst die korrekte Funktion ausgewählt werden. Wird als Template-Argument T = Foo gewählt, so sind beide Überladungen korrekt, weil Foo::Type eruierbar ist. In diesem Fall wird anhand der Regeln überladener Funktionen die näherliegende ausgewählt. Da die variadische Funktion keine Typsicherheit bietet, wird die erste Funktion (die, die einen TrueType zurückgibt) bevorzugt. Wird hingegen T = int eingegeben, so wird die erste Funktion aus der Menge der infrage kommenden Überladungen ausgeschieden. Dies erzeugt dank SFINAE keinen Kompilierfehler. Es wird außerdem die Tatsache ausgenutzt, dass der Wert 0 in C++ implizit in einen Nullzeiger konvertiert werden kann.

Ein beliebter Einsatzort von SFINAE ist das Re­s­t­rin­gie­ren bzw. ein Spezialisieren auf Typen, die eine bestimmte Gemeinsamkeit teilen. Ein Beispiel:

Wegen der Default-Template-Argumente ist das Programm nicht in C++03 lauffähig, sondern erst in C++11. Die Elemente std::enable_if etc. hingegen sind auch in C++03 implementierbar.

Dank SFINAE spart man sich hier das separate Spezialisieren des Funktionstemplates auf alle einzelnen integralen bzw. Fließkommatypen.

