SFINAE vs Concepts: Which should I use?
I've heard that C++20 Concepts can replace SFINAE. Should I still learn SFINAE?
C++20 Concepts are indeed designed to provide a more straightforward and expressive way to constrain templates compared to SFINAE. However, there are still reasons to understand SFINAE:
- Legacy codebases: Many existing C++ codebases use SFINAE extensively, especially those that make heavy use of template metaprogramming. Understanding SFINAE will be necessary to maintain and extend such codebases.
- Compiler support: While C++20 is now the current standard, not all compilers fully support all C++20 features yet, including Concepts. If you need to write code for older compilers or for environments with incomplete C++20 support, SFINAE may still be necessary.
- Understanding overload resolution: SFINAE is deeply tied to the overload resolution process in C++. Understanding how SFINAE works can deepen your understanding of this fundamental aspect of the language.
- Some advanced use cases: While Concepts cover most common use cases for constraining templates, there may still be some advanced scenarios where the flexibility of SFINAE is needed.
That said, if you are working in a C++20 environment and writing new code, Concepts should generally be preferred over SFINAE where possible. They provide a cleaner, more readable way to express requirements on template arguments.
For example, instead of using SFINAE to constrain a template parameter to types that have a Render()
member like this:
#include <type_traits>
using std::enable_if_t, std::is_same_v,
std::declval;
template <typename T, enable_if_t<is_same_v<
decltype(declval<T>().Render()), void>, int> = 0
>
void Draw(T t) {
t.Render();
}
With Concepts, you could express this more directly:
#include <concepts>
template <typename T>
concept Renderable = requires(T t) {
{ t.Render() } -> std::same_as<void>;
};
template <Renderable T>
void Draw(T t) {
t.Render();
}
In summary, while Concepts are the future for constraining templates in C++, SFINAE remains an important technique to understand, especially for working with existing codebases and in environments without full C++20 support.
Using SFINAE to Control Overload Resolution
Learn how SFINAE allows templates to remove themselves from overload resolution based on their arguments, and apply it in practical examples.