[英]SFINAE: Understanding void_t and detect_if
我正在学习模板元编程,最近,我在CPPConference上看到了一个关于 void_t 的演讲。 不久之后,我发现了检测成语。
但是,我仍然很难理解其中任何一个(尤其是检测习惯用法,因为它基于 void_t)。 我阅读了这篇博文和这篇stackoverflow 文章,这对我有所帮助,但我仍然有一些问题。
如果我的理解是正确的,如果 void_t 中的表达式无效,它将使用以下表达式进行 SFINAEd 输出:
template< class, class = std::void_t<> >
struct has_type_member : std::false_type { };
因为 class 在这里是一个默认的模板参数,它可以表示任意数量的独立于其类型的参数? 甚至有必要说 class 等于 std::void_t<> 吗? 写出来还不够
template< class, class = void >
struct has_type_member : std::false_type { };
如果不是,为什么?
但是,如果表达式有效,则此表达式将被称为计算结果为 void:
template< class T >
struct has_type_member<T, std::void_t<typename T::type>> : std::true_type { };
为什么一个有效的表达式会被评估为 void,这对我们有什么帮助? 另外,为什么表达式需要有效才能匹配 void_t?
好吧,我并没有声称我自己完全理解所有内容,但我会尽我所知尽力回答:
因为 class 在这里是一个默认的模板参数,它可以表示任意数量的独立于其类型的参数?
几乎。 此模板将匹配具有一两个模板参数的任何实例化,因此所有形式都为has_type_member<T>
或has_type_member<T, U>
。 这是因为
class
匹配任何类型。 但这并不特别(您也可以编写class T
您只是不需要名称,因为您没有在声明中引用它)每个模板最初都匹配所有类型,并且只能通过参数数量来区分。 通常情况下,我们要么通过一些 SFINAE 魔术(如enable_if
)进行约束,要么稍后通过部分模板规范更好地适应。class = void
匹配所有类型,如上所述,也根本没有类型,因为如果我们没有参数,则void
填充。 我们只会将此模板实例化为has_member_type<T>
,因此这将始终是第一个匹配项,但可能不是最佳匹配项。 但是作为第一个匹配项,它告诉我们:第二个模板参数必须是void
,因为所有进一步的匹配项必须是部分规范。 否则我们就会产生歧义。 想一想,如果表达式有效,第二个模板会给我们int
会发生什么。 然后我们有两个匹配has_type_member<T, void>
和has_type_member<T, int>
,那么我们应该选择哪个? 这就是为什么在成功的情况下,类型必须是void
然后也选择这个重载,因为它更特殊。
为什么一个有效的表达式会被评估为 void,这对我们有什么帮助? 另外,为什么表达式需要有效才能匹配 void_t?
所以第一个问题的第二部分我已经回答了。 关于第一个:想想void_t
的定义:
template<class...>
using void_t = void;
那么, ...
匹配所有类型和数量的所有内容,不是吗? 实际上它只匹配一个有效的类型,如果不匹配它怎么可能使用这种类型? (我知道它不使用该类型,但它必须能够使用。并且它不能使用无效类型)。 因此,如果传递的模板参数有效,它会给我们void
。 所以在我们的用例中:
如果T
具有成员类型T::type
,则T::type
是有效类型并且void_t<...>
匹配它。 所以我们在这一点上得到void_t<T::type>
,它的计算结果为void
,它适合主要但更特殊,所以我们取它并得到一个true_type
。
如果我们没有类型成员怎么办? 那么表达式T::type
是无效的, void_t<...>
不能对其进行 mazch,因此部分规范无效,所以我们不能选择它,但这没问题,因为替换失败不是错误,所以我们就去继续我们已经找到的主模板。
甚至有必要说 class 等于 std::void_t<> 吗? 写出来还不够
template< class, class = void > struct has_type_member : std::false_type { };
如果不是,为什么?
是的,它会,它也在谈话中完成。 void_t<>
字面上是void
。 我认为void_t
只是为了与第二个规范更一致。 需要void_t
,因为我们需要这个 template.l
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.