<p>SFINAE stands for <em>Substitution Failure Is Not An Error</em>. It's widely used by C++ in template resolution, where it has two major consequences:</p>
<ol>
<li><p>If a specific template instantiation is invalid, but there exists a different overload that would be valid, no error is reported: the invalid overload is ignored.</p>
<pre class="lang-cpp prettyprint-override"><code>#include &lt;string&gt;

template&lt;class T&gt;
void makeFive(T&amp; x) {
  x = 5;
}

template&lt;class T&gt;
void makeFive(typename T::size_type&amp; x){
  x = 5;
}

int main() {
  size_t x;
  makeFive&lt;size_t&gt;(x); // OK: uses first overload
  makeFive&lt;std::string&gt;(x); // OK: uses second overload
}
</code></pre>
</li>
<li><p>Default parameters don't cause errors if they aren't used.</p>
<pre class="lang-cpp prettyprint-override"><code>#include &lt;iostream&gt;
#include &lt;string&gt;

template&lt;class T&gt;
void print(T value = 5) {
  std::cout &lt;&lt; value &lt;&lt; std::endl;
}

int main() {
  print&lt;int&gt;(); // OK: Default value is an integer.
  print&lt;std::string&gt;(&quot;Hello, World!&quot;); // OK: Default value is unused.
  print&lt;std::string&gt;(); // Error: Default value is not a string.
}
</code></pre>
</li>
</ol>
<p>The first usage is largely unnecessary in modern languages because of interfaces and traits, but the second one is occasionally helpful. For example, when recreating <code>if</code> statements in Swift, I tried to write</p>
<pre class="lang-swift prettyprint-override"><code>func `if`&lt;T&gt;(_ condition: Bool, _ ifTrue: () -&gt; T, else ifFalse: () -&gt; T = { () -&gt; Void in () }) -&gt; T {
  condition ? ifTrue() : ifFalse()
}
</code></pre>
<p>However, Swift lacks SFINAE, so the default value for <code>ifFalse</code> causes an error.</p>
<p>What are the pros and cons to SFINAE? Why would a language with generics choose to have or not have them?</p>

<c++>
What are the pros and cons of SFINAE?
CC BY-SA 4.0
2023-06-16T09:28:29.877Z
With the addition of concepts the use cases for SFINAE in C++ are significantly reduced.
Bruce Adams
CC BY-SA 4.0
2023-06-16T09:29:18.100Z
I would say one negative consequence of being able to do it is there is less incentive to add something better to a language like concepts or refinement types.
Bruce Adams
<p>A major problem with SFINAE is that it becomes very difficult to extend the language without any possibility of breaking existing programs.  If a construct cannot appear within a valid program, then specifying a meaning for that construct and allowing programs to contain that construct would not affect the behavior of any existing valid programs, because the construct could not appear in such programs.</p>
<p>SFINAE breaks that principle, however, since it's possible for template expansion to generate invalid constructs within in valid programs.  If the constructs would be valid in a later version of the language, then a template expansion that would have failed in a manner that would have resulted in the compiler substituting another expansion, would instead succeed.  While the now-valid behavior might happen to match that of the code that would have been produced if the expansion failed, it's also possible that the other expansion might have done something totally different or (arguably worse) done something which is <em>almost</em> the same, but differs in how it handles some particular corner case.</p>

CC BY-SA 4.0
2023-07-06T22:19:21.327Z
2024-06-24T15:26:43.207Z
2024-06-24T15:26:43.207Z
supercat
<p>One problem is, it doesn't cause an error, but doesn't specify exactly why it isn't an error. If someone uses someone else's libraries without knowing how they were implemented, in situations such as defining a class implementing multiple interfaces from different sources, they may accidentally make some presumably invalid template applications valid, and break existing code.</p>
<p>This might be fixed by some other features, but with the other features, it would also be likely to remove the need of SFINAE at all.</p>

CC BY-SA 4.0
2023-07-07T03:16:29.040Z
2023-07-07T03:16:29.040Z
user23013
<p>SFINAE is a bit strange. It's only a thing in statically typed languages, because if you have dynamic types then you don't need generics. But then when you write a template, the template itself isn't type-checked, because the correctness of the template code depends on what type the parameter <code>T</code> gets realised as.</p>
<p>In other languages, if the correctness of a generic function depends on <code>T</code> meeting certain conditions, then those conditions are expressed statically in the function declaration, e.g. <code>T extends Foo</code>. This allows the function declaration to be type-checked using the knowledge of those constraints.</p>
<p>So SFINAE is sort of like &quot;dynamic typing&quot; at a meta-level; the types won't be checked until you call the function, albeit &quot;when you call the function&quot; is still at compile-time rather than runtime. The upside, I suppose, is that (like dynamic types) you can write code that works if you use it properly, without having to express in the type system itself (via <code>extends</code> constraints) which uses are &quot;proper&quot;. This might be useful if the language is not expressive enough to describe what the actual constraints are; but generally speaking, users of a statically typed language would prefer for the type system to be expressive enough instead.</p>
<p>I'll note that your second use-case is actually possible without SFINAE, if you allow function overloads like in Typescript (<a href="https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABDYB9AFBBATGsEBciARnHADYCmAhmADTLAAqATiJUegJSIC8AfIgBucGNi5ERYgNwAoUJHxIUqADxN+mHHnhgipCjXqNW7TjwGImDFADFq5AM4dE3PoKYSrchdF2MMLDBcJX0yKlobZjYXN0twAGswOAB3YzsHZz5XC0EAbwBfHjzZRDLEFkooEBYkIJD-AH4TGLciDKdKbjkC2VkAen7EOATZFXQoGIY4wSDHQwA6cjgAc3QAcmAyda4uORVVMBAAW2JKFk1gTMpp3MQAJgBmW-dEABZ7vb7BxHOWOBYDGojl+AA8AA6UaCUbBjNCHE5nC4TKY5V5PL5AA" rel="nofollow noreferrer">example</a>):</p>
<pre class="lang-typescript prettyprint-override"><code>function if_(condition: boolean, ifTrue: () =&gt; void): void;
function if_&lt;T&gt;(condition: boolean, ifTrue: () =&gt; T, ifFalse: () =&gt; T): T;
function if_(condition: boolean, ifTrue: () =&gt; unknown, ifFalse = () =&gt; {}) {
    return condition ? ifTrue() : ifFalse();
}
</code></pre>
<p>Or, of course, you could just do it without overloads by giving a different name to the version of the function which has a default argument.</p>
<hr />
<p>A more minor issue is that type-checking <em>after</em> substitutions means more work for the type checker, and hence slower compile times, because the template code has to be checked every time it gets used. (On the other hand, if a template gets used zero times then it doesn't ever have to be checked, so compiling in the presence of unused code is possibly faster.)</p>
<p>Also, errors are reported less helpfully at the call-site even if the mistake occurs in the template itself ─ and the errors are in the generated code rather than in the user's actual code, making them potentially less informative.</p>

CC BY-SA 4.0
2023-06-15T20:52:47.257Z
2023-06-17T08:23:48.750Z
2023-06-17T08:23:48.750Z
kaya3
# What are the pros and cons of SFINAE?
Posted by: username_0 on 2023-06-15
SFINAE stands for Substitution Failure Is Not An Error. It's widely used by C++ in template resolution, where it has two major consequences:

If a specific template instantiation is invalid, but there exists a different overload that would be valid, no error is reported: the invalid overload is ignored.
#include 

template
void makeFive(T& x) {
  x = 5;
}

template
void makeFive(typename T::size_type& x){
  x = 5;
}

int main() {
  size_t x;
  makeFive(x); // OK: uses first overload
  makeFive(x); // OK: uses second overload
}


Default parameters don't cause errors if they aren't used.
#include 
#include 

template
void print(T value = 5) {
  std::cout << value << std::endl;
}

int main() {
  print(); // OK: Default value is an integer.
  print("Hello, World!"); // OK: Default value is unused.
  print(); // Error: Default value is not a string.
}



The first usage is largely unnecessary in modern languages because of interfaces and traits, but the second one is occasionally helpful. For example, when recreating if statements in Swift, I tried to write
func `if`(_ condition: Bool, _ ifTrue: () -> T, else ifFalse: () -> T = { () -> Void in () }) -> T {
  condition ? ifTrue() : ifFalse()
}

However, Swift lacks SFINAE, so the default value for ifFalse causes an error.
What are the pros and cons to SFINAE? Why would a language with generics choose to have or not have them?
**Tags:** c++
> **Comments:**
> **username_1**: With the addition of concepts the use cases for SFINAE in C++ are significantly reduced.  
> **username_1**: I would say one negative consequence of being able to do it is there is less incentive to add something better to a language like concepts or refinement types.  
---
## 3 answers
### Answer by username_2 on 2023-07-06. Score: 5
A major problem with SFINAE is that it becomes very difficult to extend the language without any possibility of breaking existing programs. If a construct cannot appear within a valid program, then specifying a meaning for that construct and allowing programs to contain that construct would not affect the behavior of any existing valid programs, because the construct could not appear in such programs.

SFINAE breaks that principle, however, since it's possible for template expansion to generate invalid constructs within in valid programs. If the constructs would be valid in a later version of the language, then a template expansion that would have failed in a manner that would have resulted in the compiler substituting another expansion, would instead succeed. While the now-valid behavior might happen to match that of the code that would have been produced if the expansion failed, it's also possible that the other expansion might have done something totally different or (arguably worse) done something which is *almost* the same, but differs in how it handles some particular corner case.
---
### Answer by username_4 on 2023-06-15. Score: 3
SFINAE is a bit strange. It's only a thing in statically typed languages, because if you have dynamic types then you don't need generics. But then when you write a template, the template itself isn't type-checked, because the correctness of the template code depends on what type the parameter T gets realised as.
In other languages, if the correctness of a generic function depends on T meeting certain conditions, then those conditions are expressed statically in the function declaration, e.g. T extends Foo. This allows the function declaration to be type-checked using the knowledge of those constraints.
So SFINAE is sort of like "dynamic typing" at a meta-level; the types won't be checked until you call the function, albeit "when you call the function" is still at compile-time rather than runtime. The upside, I suppose, is that (like dynamic types) you can write code that works if you use it properly, without having to express in the type system itself (via extends constraints) which uses are "proper". This might be useful if the language is not expressive enough to describe what the actual constraints are; but generally speaking, users of a statically typed language would prefer for the type system to be expressive enough instead.
I'll note that your second use-case is actually possible without SFINAE, if you allow function overloads like in Typescript (example):
function if_(condition: boolean, ifTrue: () => void): void;
function if_(condition: boolean, ifTrue: () => T, ifFalse: () => T): T;
function if_(condition: boolean, ifTrue: () => unknown, ifFalse = () => {}) {
    return condition ? ifTrue() : ifFalse();
}

Or, of course, you could just do it without overloads by giving a different name to the version of the function which has a default argument.

A more minor issue is that type-checking after substitutions means more work for the type checker, and hence slower compile times, because the template code has to be checked every time it gets used. (On the other hand, if a template gets used zero times then it doesn't ever have to be checked, so compiling in the presence of unused code is possibly faster.)
Also, errors are reported less helpfully at the call-site even if the mistake occurs in the template itself ─ and the errors are in the generated code rather than in the user's actual code, making them potentially less informative.
---
### Answer by username_3 on 2023-07-07. Score: 2
One problem is, it doesn't cause an error, but doesn't specify exactly why it isn't an error. If someone uses someone else's libraries without knowing how they were implemented, in situations such as defining a class implementing multiple interfaces from different sources, they may accidentally make some presumably invalid template applications valid, and break existing code.

This might be fixed by some other features, but with the other features, it would also be likely to remove the need of SFINAE at all.
---
