Using SFINAE to Check for Member Types
Can I use SFINAE to check if a type has a specific member type?
Yes, SFINAE can be used to check for the presence of member types in a similar way to how it's used to check for member functions.
Let's say we want to write a template function foo
that only accepts types T
that have a member type named value_type
. We can achieve this using SFINAE like this:
#include <iostream>
#include <type_traits>
template <typename T,
typename = std::enable_if_t<
std::is_same_v<typename T::value_type, int>>
>
void foo(T) {
std::cout << "T has a value_type member"
" of type int\n";
}
struct A {
using value_type = int;
};
struct B {
using value_type = double;
};
struct C {
// no value_type member
};
int main() {
// OK, A::value_type is int
foo(A{});
// Substitution failure, B::value_type is not int
foo(B{});
// Substitution failure, C has no value_type
foo(C{});
}
Here, the second template parameter of foo
is an unused type parameter. The std::enable_if
condition checks if T::value_type
exists and is the same type as int
.
If T
has a value_type
member type that is int
, the condition is true and foo
is viable. If T
doesn't have a value_type
member, or if it has one but it's not int
, a substitution failure occurs, removing this foo
template from the overload set.
Note that we use typename T::value_type
to refer to the member type. The typename
keyword is necessary to tell the compiler that value_type
is a type, because it's dependent on the template parameter T
.
This technique can be used to check for the presence and properties of any member type, not just value_type
. It's a powerful tool for template metaprogramming and can be used to implement traits and concepts in pre-C++20 code.
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.