简体   繁体   English

SFINAE:了解 void_t 和 detect_if

[英]SFINAE: Understanding void_t and detect_if

I'm learning about template metaprogramming, and recently, I saw a talk on the CPPConference about void_t.我正在学习模板元编程,最近,我在CPPConference上看到了一个关于 void_t 的演讲。 Soon after that, I found out about the detection idiom .不久之后,我发现了检测成语

However, I still have a hard time understanding either one of them (especially the detection idiom, since it's based on void_t).但是,我仍然很难理解其中任何一个(尤其是检测习惯用法,因为它基于 void_t)。 I read this blog post, and this stackoverflow post, which helped me a bit, but I still have some questions.我阅读了这篇博文和这篇stackoverflow 文章,这对我有所帮助,但我仍然有一些问题。

If my understanding is right, if an expression inside void_t is invalid, it will be SFINAEd out using this expression:如果我的理解是正确的,如果 void_t 中的表达式无效,它将使用以下表达式进行 SFINAEd 输出:

template< class, class = std::void_t<> >
struct has_type_member : std::false_type { };

Because class is here a default template parameter that can represent any number of parameters independent of their type?因为 class 在这里是一个默认的模板参数,它可以表示任意数量的独立于其类型的参数? Is it even necessary to say that class equals to std::void_t<> ?甚至有必要说 class 等于 std::void_t<> 吗? Wouldn't it be enough to write写出来还不够

template< class, class = void >
struct has_type_member : std::false_type { };

And if not, why?如果不是,为什么?

However, if the expression is valid, this expression will be called an evaluated to void:但是,如果表达式有效,则此表达式将被称为计算结果为 void:

template< class T >
struct has_type_member<T, std::void_t<typename T::type>> : std::true_type { };

Why would a valid expression be evaluated to void, and how does this help us?为什么一个有效的表达式会被评估为 void,这对我们有什么帮助? Also, why does the expression need to be valid to match void_t?另外,为什么表达式需要有效才能匹配 void_t?

Ok, I don't claim that I habe understood all perfectly, myself, but I will try to answer to the best of my knowledge:好吧,我并没有声称我自己完全理解所有内容,但我会尽我所知尽力回答:

Because class is here a default template parameter that can represent any number of parameters independent of their type?因为 class 在这里是一个默认的模板参数,它可以表示任意数量的独立于其类型的参数?

Nearly.几乎。 This template will match any instantiation with one or two template arguments, so all of the form has_type_member<T> or has_type_member<T, U> .此模板将匹配具有一两个模板参数的任何实例化,因此所有形式都为has_type_member<T>has_type_member<T, U> This is due to这是因为

  • class matches any type. class匹配任何类型。 But this not special (you could also write class T you just don't need the name, cause you don't reference it in the declaration) Every template at first matches all types and could only be differentiated by the number of arguments.但这并不特别(您也可以编写class T您只是不需要名称,因为您没有在声明中引用它)每个模板最初都匹配所有类型,并且只能通过参数数量来区分。 Just often, we have either a constraint through some SFINAE-magic (like enable_if ) or we have a better fit by partial template specification later on.通常情况下,我们要么通过一些 SFINAE 魔术(如enable_if )进行约束,要么稍后通过部分模板规范更好地适应。
  • class = void matches every type, as above and also no type at all, since void fills in if we have no argument. class = void匹配所有类型,如上所述,也根本没有类型,因为如果我们没有参数,则void填充。

We will only instantiate this template as has_member_type<T> , so this will always be the first match, but maybe not the best match.我们只会将此模板实例化为has_member_type<T> ,因此这将始终是第一个匹配项,但可能不是最佳匹配项。 But being the first match, it tells us: The second template argument has to be void , since all further matches must either be a partial specification.但是作为第一个匹配项,它告诉我们:第二个模板参数必须是void ,因为所有进一步的匹配项必须是部分规范。 Otherwise we would get ambiguity.否则我们就会产生歧义。 Think, what would happen if the second template would give us int if the expression is valid.想一想,如果表达式有效,第二个模板会给我们int会发生什么。 Then we had two matches has_type_member<T, void> and has_type_member<T, int> , so which should we choose?然后我们有两个匹配has_type_member<T, void>has_type_member<T, int> ,那么我们应该选择哪个? That is why in the success case the type has to be void and then this overload is also chosen, since it is more special.这就是为什么在成功的情况下,类型必须是void然后也选择这个重载,因为它更特殊。

Why would a valid expression be evaluated to void, and how does this help us?为什么一个有效的表达式会被评估为 void,这对我们有什么帮助? Also, why does the expression need to be valid to match void_t?另外,为什么表达式需要有效才能匹配 void_t?

So the second part of the first question I already answered.所以第一个问题的第二部分我已经回答了。 Regarding the first: Think of the definition of void_t :关于第一个:想想void_t的定义:

template<class...>
using void_t = void;

So, ... matches everything regardless of type and number, doesn't it?那么, ...匹配所有类型和数量的所有内容,不是吗? Actually it only match a valid type, if not how would it potentially use this type?实际上它只匹配一个有效的类型,如果不匹配它怎么可能使用这种类型? (I know it doesn't use the type, but it has to be able to. And it cannot use an invalid type). (我知道它不使用该类型,但它必须能够使用。并且它不能使用无效类型)。 Therefore it gives us void if the template argument(s) passed are valid.因此,如果传递的模板参数有效,它会给我们void So in our use case:所以在我们的用例中:

If T has a member type T::type , T::type is a valid type and void_t<...> matches it.如果T具有成员类型T::type ,则T::type是有效类型并且void_t<...>匹配它。 So we get void_t<T::type> at this point, which evaluates to void , that fits to the primary but is more special, so we take it and get a true_type .所以我们在这一点上得到void_t<T::type> ,它的计算结果为void ,它适合主要但更特殊,所以我们取它并得到一个true_type

What about if we have no type member?如果我们没有类型成员怎么办? Then the expression T::type is invalid, void_t<...> cannot mazch it and hence the partial specification is invalid, so we cannot chose it, but this no problem, since Substitution Failure Is Not An Error, so we just go on with what we already found, the primary template.那么表达式T::type是无效的, void_t<...>不能对其进行 mazch,因此部分规范无效,所以我们不能选择它,但这没问题,因为替换失败不是错误,所以我们就去继续我们已经找到的主模板。

Is it even necessary to say that class equals to std::void_t<> ?甚至有必要说 class 等于 std::void_t<> 吗? Wouldn't it be enough to write写出来还不够

template< class, class = void > struct has_type_member : std::false_type { };

And if not, why?如果不是,为什么?

Yes, it would, it is also done in the talk.是的,它会,它也在谈话中完成。 void_t<> is literally void . void_t<>字面上是void I think the void_t is only taken to be more consistent with the second specification.我认为void_t只是为了与第二个规范更一致。 There void_t is needed, since we need this template.l需要void_t ,因为我们需要这个 template.l

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM