Ugrás a tartalomhoz

substitution failure is not an error

A Wikiszótárból, a nyitott szótárból


Főnév

substitution failure is not an error (tsz. substitution failure is not an errors)

  1. (informatika) SFINAE (Substitution Failure Is Not An Error) egy haladó C++ sablonmechanizmus, ami lehetővé teszi, hogy a sablonpéldányosítás során keletkező típushelyettesítési hibák ne okozzanak fordítási hibát, hanem a fordító egyszerűen kizárja a nem illeszkedő sablont a lehetséges opciók közül.



🧠 Lényege

Amikor egy sablonfüggvény vagy sablonosztály példányosítása során a típusparaméterek behelyettesítésekor fordítási hiba keletkezne, a fordító nem dob hibát, hanem kihagyja ezt a verziót a túlterhelésből. Így a fordító másik overload-ot keres helyette.



🔧 Egyszerű példa

template<typename T>
void printIfIntegral(T value) {
    static_assert(std::is_integral<T>::value, "T must be an integral type");
    std::cout << "Egész szám: " << value << std::endl;
}

Ez fordítási hibát dob, ha T nem egész szám.

De:

template<typename T>
typename std::enable_if<std::is_integral<T>::value>::type
printIfIntegral(T value) {
    std::cout << "Egész szám: " << value << std::endl;
}

Ez a változat csak akkor fordul le, ha T egy int, char, long, stb. – vagyis std::is_integral<T>::value == true.

Ha nem az, a sablon példányosítása meghiúsul – de nem hiba! A fordító egyszerűen tovább keres másik overload-ot.



🧪 Konkrét példa túlterheléssel

#include <iostream>
#include <type_traits>

template<typename T>
typename std::enable_if<std::is_integral<T>::value>::type
foo(T x) {
    std::cout << "Egész típus" << std::endl;
}

template<typename T>
typename std::enable_if<std::is_floating_point<T>::value>::type
foo(T x) {
    std::cout << "Lebegőpontos típus" << std::endl;
}

Használat:

foo(42);    // Egész típus
foo(3.14);  // Lebegőpontos típus

A fordító az enable_if segítségével kizárja azt a verziót, ami nem alkalmazható – ez a SFINAE működése.



📜 enable_if röviden

template<bool B, typename T = void>
struct enable_if {};

template<typename T>
struct enable_if<true, T> { using type = T; };

Tehát ha a feltétel igaz, akkor van ::type, különben nincs → a típushelyettesítés meghiúsul.



🔎 SFINAE alkalmazási területek

  • Overload kiválasztás típus alapján
  • Kompiláció idejű feltételes aktiválás
  • Sablongenerikus kód testreszabása
  • STL belső működés (pl. std::vector konstruktora)



🛑 Mikor nem működik?

SFINAE csak sablonpéldányosítás során működik. Ha a hiba nem a példányosításkor, hanem az általános sablon definícióban van (pl. szintaktikai hiba), akkor az valódi hiba lesz.



🧰 Modern C++ rövidítés (C++14, C++17)

Függvény sablon rövidítés (C++14):

template<typename T>
std::enable_if_t<std::is_integral_v<T>>
foo(T x) {
    std::cout << "Integral" << std::endl;
}
  • enable_if_t = rövidítés typename std::enable_if<...>::type
  • is_integral_v<T> = rövidítés std::is_integral<T>::value



🔄 Alternatíva: if constexpr (C++17-től)

template<typename T>
void foo(T x) {
    if constexpr (std::is_integral_v<T>) {
        std::cout << "Egész szám" << std::endl;
    } else {
        std::cout << "Nem egész szám" << std::endl;
    }
}

Ez nem SFINAE, hanem kompiláció idejű feltételes ágak – de sok esetben könnyebben olvasható és fenntartható.



🧩 Összefoglalás

Fogalom Jelentés
SFINAE A sablonpéldányosítás során fellépő típushelyettesítési hibák nem dobják meg a fordítót, csak kizárják a sablont
Eszköz std::enable_if, std::is_integral, decltype, sizeof, stb.
Használat Overload kiválasztás, kompiláció idejű viselkedés módosítás
Alternatíva if constexpr C++17-től, koncepciók (concepts) C++20-tól