Roadmap to becoming a developer in 2022
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

2.1 KiB

SFINAE (Substitution Failure Is Not An Error)

SFINAE is a principle in C++ template metaprogramming that allows the compiler to select the appropriate function or class when a specific template specialization fails during substitution. The term "substitution failure" refers to the process where the compiler tries to substitute template arguments into a function template or class template. If the substitution causes an error, the compiler won't consider that specific specialization as a candidate and will continue searching for a valid one.

The key idea behind SFINAE is that if a substitution error occurs, it is silently ignored, and the compiler continues to explore other template specializations or overloads. This allows you to write more flexible and generic code, as it enables you to have multiple specializations for different scenarios.

Code Example

Here's an example that demonstrates SFINAE in action:

#include <iostream>
#include <type_traits>

template <typename T, typename = void>
struct foo_impl {
    void operator()(T t) {
        std::cout << "Called when T is not arithmetic" << std::endl;
    }
};

template <typename T>
struct foo_impl<T, std::enable_if_t<std::is_arithmetic<T>::value>> {
    void operator()(T t) {
        std::cout << "Called when T is arithmetic" << std::endl;
    }
};

template <typename T>
void foo(T t) {
    foo_impl<T>()(t);
}

int main() {
    int a = 5;
    foo(a); // output: Called when T is arithmetic

    std::string s = "example";
    foo(s); // output: Called when T is not arithmetic
}

In this example, we define two foo_impl functions are specialized based on the boolean value of std::is_arithmetic<T>. The first one is enabled when T is an arithmetic type, while the second one is enabled when T is not an arithmetic type. The foo function then calls the appropriate foo_impl specialization based on the result of the type trait.

When calling foo(a) with an integer, the first specialization is selected, and when calling foo(s) with a string, the second specialization is selected. If there is no valid specialization, the code would fail to compile.