void_t spezialization为什么主模板必须有default = void?

时间:2015-07-07 09:44:12

标签: c++ sfinae tmp

我对此视频中显示的void_t元函数有疑问 https://www.youtube.com/watch?v=a0FliKwcwXE以及41:25提出的问题。

我将尝试使用此代码段显示我的问题:

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
{
};

为什么第一个模板需要默认类型void? int不起作用。

我的理解是两个函数都具有相同的签名(带有void)但是将使用更多的spezialized(第二个)。 但为什么它不适用于int?有空的第二个仍然是首选的那个不是吗?

= int不匹配SFINAE吗?

谢谢!

1 个答案:

答案 0 :(得分:4)

需要

void,以便void_t<decltype(...)>表达式的结果与主模板的默认参数匹配。

考虑类是否可分配的情况:

可分配:

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

不可转让:

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

现在在可分配的情况下,只有在模板参数匹配时才会选择部分特化,即它们必须是以下形式:

__is_assignable_helper_af2<_Tp, _Up, void>

我们希望客户端代码只传递两个参数,而不是显式指定SFINAE的void参数,因此我们在默认参数中指定它:

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

我们可以轻松地选择void以外的类型,但使用它可以明确我们不关心类型,我们只是用它来利用SFINAE。例如,我们可以定义int_t并将int作为默认参数。只要它们匹配,我们就会在需要时使用部分特化。