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.
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.