# SFINAE **SFINAE** (substitution failure is not an error) is the rule that when the compiler substitutes a candidate template's arguments during overload resolution and the substitution produces an invalid type or expression, that candidate is silently removed from the overload set instead of triggering a hard compile error. It's the mechanism that lets library code write multiple template overloads that only "exist" for types satisfying some property, without the caller ever seeing the ones that don't apply. ```cpp template auto has_size(int) -> decltype(std::declval().size(), std::true_type{}); template auto has_size(...) -> std::false_type; static_assert(decltype(has_size>(0))::value); // true static_assert(!decltype(has_size(0))::value); // false ``` ## Why "not an error" is the whole point Ordinarily, referencing a nonexistent member (`.size()` on a type that has none) is a hard compile error. Inside a template's immediate context during argument deduction, though, an invalid expression just disqualifies that overload from consideration, as if it had never been written, and the compiler moves on to try the other candidates. This only applies to the **immediate context** of substitution: an error that only shows up once inside the function body (after substitution has already succeeded) is a real, hard compile error, not SFINAE. The `int` vs `...` (ellipsis) pair above exploits overload resolution's preference for an exact match, `int`, over a variadic fallback, so when the `decltype` expression in the first overload is well-formed, it wins; when it isn't, SFINAE removes that overload and the `...` fallback is the only one left. ## Where it actually shows up The classic use is `std::enable_if`, which turns a template parameter into a "does this substitution succeed" gate: writing `enable_if_t>` as an extra defaulted template parameter makes an overload disappear entirely for non-integral `T`, rather than compiling and misbehaving. ```cpp template >> void process(T value) { /* only participates in overload resolution for integral T */ } ``` Modern code increasingly reaches for `if constexpr` or C++20 concepts (`requires` clauses) instead of hand-rolled SFINAE, since both express the same "only valid for types with this property" intent far more readably. SFINAE is still worth understanding on its own terms, though, because it's the mechanism `enable_if`, `void_t`-based detection idioms, and concepts under the hood are all built from, and a huge amount of pre-C++20 template metaprogramming in existing codebases is written directly in terms of it. ## Links - https://en.cppreference.com/w/cpp/language/sfinae.html