Search code examples
c++sfinaetype-deductiontemplate-argument-deduction

Does SFINAE depend on type deduction?


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?


Solution

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