enable_if
- C++ course
- Advanced
- Lesson 15/83
- 5 min
Learn SFINAE with enable_if.
enable_if (SFINAE)
std::enable_if produces a valid type when a condition is true and nothing when it is false. This relies on SFINAE (Substitution Failure Is Not An Error); a failed overload is silently dropped from the candidate set.
Example: template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>> T add_one(T x). This overload is a candidate only when T is an integer. add_one(5) works; add_one(std::string{...}) fails to compile. Before concepts this was the main tool to constrain templates.
Using enable_if_t
enable_if_t<cond> returns void (or a second parameter type) when the condition is true. It is commonly placed as a default template parameter: template <typename T, typename = std::enable_if_t<cond>>. This adds an invisible constraint to the signature.
Before C++17 you wrote typename std::enable_if<cond>::type. The _t suffix shortens it. In modern C++ concepts are a cleaner alternative, but enable_if is common in legacy code and worth knowing.
Practice Constrain add_one
Write template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>> T add_one(T x). The body should be return x + 1;. In main write std::cout << add_one(5);.
Starter code
#include <iostream>
#include <type_traits>
// Write add_one with enable_if
int main() {
// Call add_one(5) and print
return 0;
}Sample solution
#include <iostream>
#include <type_traits>
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
T add_one(T x) {
return x + 1;
}
int main() {
std::cout << add_one(5);
return 0;
}Expected output
6
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 What does SFINAE stand for?
- Single Function Is Not An Error
- Static Function In A Namespace
- Substitution Failure Is Not An Error Correct answer
- Safe Function In Any Execution
Explanation: SFINAE stands for Substitution Failure Is Not An Error.
2 Match each expression to its role
| Term | Meaning |
|---|---|
std::enable_if_t<cond> |
Type when condition is true |
std::is_integral_v<T> |
The condition expression |
typename = ... |
Empty default argument |
add_one(5) |
A valid call |
3 Complete the enable_if line
template <typename T, typename = std::____<std::is_integral_v<T>>
T add_one(T x) { return x + 1; }
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>
T add_one(T x) { return x + 1; }
Explanation: enable_if_t<cond> yields a type when the condition is true.