I am confused about the following quote in cppreference.com:
This rule applies during overload resolution of function templates: When substituting the deduced type for the template parameter fails, the specialization is discarded from the overload set instead of causing a compile error.
Does it mean that SFINAE cannot work without type deduction? For instance, consider the following code:
template <typename T> std::true_type has_value_type_helper(typename T::value_type*);
template <typename> std::false_type has_value_type_helper(...);
template <typename T> inline constexpr bool has_value_type_v
= decltype(has_value_type_helper<T>(nullptr))::value;
int main() {
std::cout << has_value_type_v<int> << std::endl;
std::cout << has_value_type_v<std::vector<int>> << std::endl;
}
It works as expected but as far as I can see, there is no type deduction. The template argument is provided explicitly in has_value_type_helper<T>(nullptr)
. Can even SFINAE be used this way?
Can even SFINAE be used this way?
Yes.
Substitution is part of the deduction process. Explicitly providing template arguments does not obviate the need for substitution ([temp.deduct]/2) - and it's the substitution (the S in SFINAE) failure that is not an error ([temp.deduct]/8).
In this case, when you explicitly provide T
to has_value_type_helper
, we still need to substitute T
into the argument T::value_type
. That is in the immediate context of the substitution, so if that substitution fails - which it would for types like int
which do not have a nested type alias named value_type
- it's... not an error, we just remove the candidate from consideration. We have another backup candidate, so this works fine.