1

i've got a question about the void_t metafunction, shown in this video https://www.youtube.com/watch?v=a0FliKwcwXE and the question asked at 41:25.

I'll try to show my question with this code snippet:

template<typename _Tp, typename _Up, typename = void>
class __is_assignable_helper_af2: public std::false_type
{
};


template<typename _Tp, typename _Up>
class __is_assignable_helper_af2<_Tp, _Up,
     void_t<decltype(std::declval<_Tp&>() = std::declval<_Up&>())>> 
  : public std::true_type
{
};

Why does the first template need the default type void ? int doesn't work.

What I understand is that both functions will have the same signature ( with void) but the more spezialized will be used (the second). But why does it not work with int ? The second one with void would still be the prefered one would't it ?

Would the =int not match SFINAE ?

thanks!

AF_cpp
  • 568
  • 5
  • 15

1 Answers1

4

void is needed so that the result of that void_t<decltype(...)> expression will match the default argument for the primary template.

Think about the cases in which the classes are and are not assignable:

Are assignable:

void_t<decltype(std::declval<_Tp&>() = std::declval<_Up&>())>
//reduces to
void_t<type given from assignment>
//reduces to
void

Are not assignable:

void_t<decltype(std::declval<_Tp&>() = std::declval<_Up&>())>
//substitution failure, remove from candidate set

Now in the assignable case, the partial specialization will only be selected if the template arguments match, i.e. they need to be of the form:

__is_assignable_helper_af2<_Tp, _Up, void>

We want client code to just pass two arguments rather than explicitly specifying the void argument for the SFINAE to take place, so we specify it in the default arguments:

template<typename _Tp, typename _Up, typename = void>
//                                   ^^^^^^^^^^^^^^^

We could just as easily choose a type other than void for this, but using it makes it explicit that we don't care about the type, we are just using it to leverage SFINAE. For example, we could define int_t and have int as the default argument instead. So long as they match, we use the partial specialization when we want to.

TartanLlama
  • 63,752
  • 13
  • 157
  • 193