Open In App

Substitution Failure Is Not An Error (SFINAE) in C++

Last Updated : 02 Jan, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Prerequisite: Templates in C++

Substitution Failure Is Not An Error (SFINAE) is a principle of the C++ programming language that states that a compiler should not fail to compile a program just because it cannot substitute a template parameter. This principle allows for the use of template metaprogramming and enables the compiler to make decisions based on the types of template arguments, which can be useful when dealing with complex code and difficult to reason about logic.

At its core, SFINAE is a way of allowing a compiler to decide which template to use in a given context. The decision is based on the types of template arguments and the compiler will choose the template that is most appropriate for the arguments. 

Advantages of SFINAE:

  1. SFINAE is useful in a variety of scenarios, including writing generic code and dealing with complex logic. 
  2. SFINAE allows the compiler to decide which template to use, it allows programmers to write code that can be reused in different contexts without needing to explicitly specify the types of template parameters.
  3. SFINAE allows for better code reuse, as the same code can be used for different types of objects and parameters.
  4. SFINAE also allows for better control over code complexity by allowing the compiler to make decisions based on the types of template parameters, it can reduce the amount of complex logic that needs to be written and understood. 
  5. SFINAE helps to make code more readable and maintainable, as it is easier to follow the logic of the program.

In conclusion, SFINAE is a powerful concept in C++ programming that allows for better code reuse, improved code readability, and better control over code complexity. It is a key component of template metaprogramming and is an essential tool for writing robust and efficient code.

Example:

C++




// C++ Program to implement
// Substitution Failure Is Not An Error
#include <iostream>
#include <type_traits>
  
using namespace std;
  
// USing template to avoid errors
template <typename T> 
void print_type(T t)
{
    // For integer
    if (is_integral<T>::value) {
        cout << "T is an integral type" << endl;
    }
  
    // For floating number
    else if (is_floating_point<T>::value) {
        cout << "T is a floating point type" << endl;
    }
  
    // All other
    else {
        cout << "T is not an integral"
             << "or floating point type" << endl;
    }
}
  
// Driver Code
int main()
{
    // T is an integral type
    print_type(10);
  
    // T is a floating point type
    print_type(10.5f);
  
    // T is an integral type
    print_type(true);
  
    // T is an integral type
    print_type('a');
  
    // T is not an integral
    //  or floating point type
    print_type("GFG");
  
    return 0;
}


Output

T is an integral type
T is a floating point type
T is an integral type
T is an integral type
T is not an integralor floating point type

In this example, the print_type() function is a template function that takes a single argument of type T. Inside the function, there are if statements that use the is_integral and is_floating_point type traits to check the type of T. If T is of the expected type, the corresponding branch of the if statement is executed and the appropriate message is printed. If T is not of the expected type, the else branch is executed and the message “T is not an integral or floating point type” is printed.

SFINAE is used in this example because the if statement uses type traits to check the type of T, and if T is not of the expected type, the template substitution will fail. However, because SFINAE is in effect, this failure is not treated as a compile-time error, and the else branch is executed instead.

Disadvantages of SFINAE

Although SFINAE is very useful it comes with its own limitations, these are :

  1. It can be difficult to debug and understand the underlying code, as it relies heavily on the templates and multiple overloads to work correctly.
  2. SFINAE is not widely used and can be difficult to find documentation and tutorials for.
  3. SFINAE can produce unexpected behavior, as it relies on the compiler to determine which template to use based on the given types. This can lead to unexpected results if the compiler chooses the wrong template.
  4. SFINAE can also be slow, as it involves multiple checks in order to determine the correct template. This can lead to a performance hit if used in a critical section of code.

There are other methods to perform the same task one of which is enable_if

Enable_if (Syntax)

template<typename T>
enable_if_t<is_integral<T>, void> f(T x)
{
  // code that only applies to integral types goes here
}


Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads