ENABL
我知道C ++编译器优先选择一个模板专业化:
template<class T, class Enable = void>
class A {}; // primary template
template<class T>
class A<T, std::enable_if_t<std::is_floating_point_v<T>, void>> {
}; // specialization for floating point types
但是,我不明白为什么选择void
以外的其他类型被用作参数to enable_if时,选择了。
:
template<class T>
class A<T, std::enable_if_t<std::is_floating_point_v<T>, int>> {
}; // specialization for floating point types
编译器肯定会“请参阅” a&lt; t,int&gt;
。 因此,它当然不能是Sfinae,但是,主要模板比专业化更喜欢。
这个问题是从可以使用自定义类型检测机械而不是enable_if
的上下文中引起的,例如common_type
,例如sfinae友好型提取器。
I know that a C++ compiler picks a template specialization in preference to the primary template:
template<class T, class Enable = void>
class A {}; // primary template
template<class T>
class A<T, std::enable_if_t<std::is_floating_point_v<T>, void>> {
}; // specialization for floating point types
However, I don't understand why the selection fails when a type other than void
is used as argument to enable_if
:
template<class T>
class A<T, std::enable_if_t<std::is_floating_point_v<T>, int>> {
}; // specialization for floating point types
The compiler would surely "see" class A<T, int>
.
So it certainly can't be SFINAE, nevertheless the primary template is preferred to the specialization.
This question arises from a context where a custom type detection machinery could be used instead of enable_if
, e.g. an SFINAE friendly type extractor like common_type
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您拥有
模板参数为
some_floating_point_type
和隐式void
。当编译器实例化时,它将获得
a&lt; some_floating_point_type,int&gt;
,与a&lt; some_floating_point_point_type不匹配, 。因此,专业被忽略,您将获得主模板。您可以通过尝试创建一个
a&lt; some_floating_point_type,int&gt;
来验证这一点,并且您会选择选择专业化。我发现将专业视为替代食谱很有帮助。首先,推导了模板参数,然后如果它们匹配任何专业,则我们切换到使用该替代配方。如果不是,则使用原始食谱。
When you have
The template parameters are
some_floating_point_type
and the implicitvoid
. When the compiler instantiatesit would get
A<some_floating_point_type, int>
, which does not match theA<some_floating_point_type, void>
type thatsome_name
has. Because of that, the specialization is ignored and you get the primary template. You can verify this by trying to create aA<some_floating_point_type, int>
and you'll get that the specialization was picked.I find it helpful to think of a specialization as an alternate recipe. First the template arguments are deduced, and then if they match any of the specializations, then we switch to using that alternate recipe. If not, then the original recipe is used.
在编译器知道将用于 primary 模板的类型之前,专业是无关紧要的。
当您编写
a&lt; double&gt;
时,编译器仅查看主模板,并看到您实际上是指a&lt; double,void&gt;
。只有然后它正在寻找专业。现在,当您的专业化是
a&lt; double,int&gt;
时,它不合适,因为您要求a&lt; double,void&gt;
。Specializations are irrelevant until the compiler knows which types it is going to use for the primary template.
When you write
A<double>
, then the compiler looks only at the primary template and sees that you actually meanA<double,void>
.And only then it is looking for specializations. Now, when your specialization is for
A<double,int>
, then it is not suitable because you asked forA<double,void>
.简而言之,这
说明“ a是一个模板,它有两个参数,第二个参数具有
void
>”。多数民众赞成在主要模板。当您明确提供一个参数时,第二个参数是void
。现在专业:
这不会改变上述内容。
a
仍然是一个带有2个参数的模板,当未指定第二个参数时,它是void
。简而言之,这意味着“在t
中替换std :: enable_if_t&lt&lt&lt&lt :: is_floating_point_point_voint_v&lt; t&gt;
是失败,因为类型别名不存在”条件是false
,Sfinae启动,并且专业化被忽略。当条件为true
时:“每当A与参数t(某种类型)和int
实例化时,然后使用此定义”。当您实例化
a&lt; int&gt;
时,第二个模板参数为void
。专业并没有改变这一点。那就是a&lt; int
实际上是a&lt; int,void&gt;
。它不符合专业化。In simple terms, this
says "A is a template, it has two arguments, the second has a default that is
void
". Thats the primary template. When you explicitly provide only one parameter then the second argument isvoid
.Now the specialization:
This doesn't change the above.
A
is still a template with 2 arguments and when the second one is not specified then it isvoid
. In simple terms it either means "substitutingT
instd::enable_if_t<std::is_floating_point_v<T>
is a failure, because the type alias does not exist" when the condition isfalse
, SFINAE kicks in and the specialization is ignored. When the condition istrue
: "Whenever A is instantiated with arguments T (some type) andint
then use this definition".When you instantiate
A<int>
then the second template argument isvoid
. The specialization does not change that. That isA<int>
is actuallyA<int,void>
. It does not match the specialiazation.