我对此视频中显示的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吗?
谢谢!
答案 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
作为默认参数。只要它们匹配,我们就会在需要时使用部分特化。