Search code examples
c++templatestemplate-specializationenable-if

Difference between template specialization and SFINAE with std::enable_if?


If I have a template function in C++, and want it to behave in a different manner in presence of a specific template parameter, I will use a template specialization:

#include <iostream>
#include <type_traits>

template<typename T> void myFunction(T&& input) {
    std::cout << "The parameter is " << input << '\n';
}

template<> void myFunction<int>(int&& input) {
    std::cout << "Double of the parameter is " << 2 * input << '\n';
}

int main() {
    myFunction(24.2);
    myFunction(24);
    myFunction("Hello");
}

Use of std::enable_if<bool B> from <type_traits> enables to activate a similar behaviour for some specific template types. Any other type would cause a substitution error.

#include <iostream>
#include <type_traits>

template<typename T, std::enable_if_t<std::is_integral_v<T>>* = nullptr > 
void myFunction(T&& input) {
    std::cout << "Double of the parameter is " << 2 * input << '\n';
}

template<typename T, std::enable_if_t<std::is_floating_point_v<T>>* = nullptr > 
void myFunction(T&& input) {
    std::cout << "The parameter is " << input << '\n';
}

int main() {
    myFunction(24.2);
    myFunction(24);
    // myFunction("Hello"); // compile-time substitution error
}

My question is: what is really the gain of using the fancier std::enable_if specialization, in place of the standard template specialization? Are they really alternatives, or std::enable_if is exclusively for template metaprogramming?


Solution

  • These 2 approaches are executed on different stages. First is overload resolution - on this stage template specialization is not used. Only generic template function prototype is in use.

    On the other hand SFINAE approach drops the overloads that failed to be substituted silently on this stage leaving only one candidate based on enable_if conditions.

    Second step is template instantiation - here the body of your function is created - and it will use body provided by most specialized template.