Yes, SFINAE can be applied to variadic templates. This is often used to check properties of the types in a parameter pack.
Here's an example that implements a are_all_same
function that checks if all types in a variadic template are the same:
#include <iostream>
#include <type_traits>
template <typename T, typename... Rest>
constexpr bool are_all_same() {
return (std::is_same_v<T, Rest> && ...);
}
template <typename... Ts, std::enable_if_t<
are_all_same<Ts...>(), int> = 0>
void foo(Ts...) {
std::cout << "All types are the same\n";
}
template <typename... Ts, std::enable_if_t<
!are_all_same<Ts...>(), int> = 0>
void foo(Ts...) {
std::cout << "Types are not all the same\n";
}
int main() {
foo(1, 2, 3); // Uses second template
foo(1, 2, 3.14); // Uses second template
foo(1, 1, 1); // Uses first template
}
All types are the same
Types are not all the same
All types are the same
Here, are_all_same
is a variadic template function that uses a fold expression to check if all types in the parameter pack Ts...
are the same.
We then have two foo
function templates. The first one is enabled if are_all_same<Ts...>()
is true, i.e., if all types in Ts...
are the same. The second one is enabled if are_all_same<Ts...>()
is false.
When we call foo(1, 2, 3)
, all arguments are of type int
, so are_all_same<int, int, int>()
is true. Therefore, the first foo
template is selected.
When we call foo(1, 2, 3.14)
, the arguments are of different types (int
and double
), so are_all_same<int, int, double>()
is false. Therefore, the second foo
template is selected.
This demonstrates how SFINAE can be used with variadic templates to enable or disable function templates based on properties of the entire parameter pack. This can be a powerful tool for implementing type traits and concepts that depend on variadic templates.
Answers to questions are automatically generated and may not have been reviewed.
Learn how SFINAE allows templates to remove themselves from overload resolution based on their arguments, and apply it in practical examples.