我很难理解bool的模板特化如何适用于cppcon 2017
的幻灯片简短问题:为什么(第一个)主要模板在签名
时处理奇数 N个案例< ...,bool = (N%2 == 0)> ?
试图了解自己,我简化为
#include<iostream>
template<unsigned N, bool =(N%2==0)> struct S { void operator()(){ std::cout << "A\n"; } };
template<unsigned N> struct S<N, true> { void operator()(){ std::cout << "B\n"; } };
int main()
{
S<2>{}();
S<3>{}();
}
打印B
A
,显示与链接谈话相同(但对我来说神秘)行为,但如果我将模板专精化更改为
template<unsigned N> struct S<N, false> { void operator()(){ std::cout << "B\n"; } };
-----
它打印A
B
:编译器如何在主S
及其专业化之间进行选择?
答案 0 :(得分:1)
编译器总是更喜欢泛化的特化,因此如果可以,它总是会选择它。
struct S
有一个部分模板特化,只有在第二个模板参数的计算结果为true
时才会被选中,所以让我们看看它是如何工作的:
S<2>{}();
此处模板参数N
为2,因此2 % 2 == 0
成立。这意味着将在广义S
上挑选专业化,因为专业化要求第二个参数为true
并打印B
。
S<3>{}();
不是这种情况,因为3 % 2 == 0
保持为false,因此会使用广义情况,为您提供A
。
如果你交换它并使专门化只接受false
N % 2 == 0
,那么结果将完全相反,2 % 2 == 0
仍然成立,但专业化只接受假,所以它是未选中,3 % 2 == 0
保持为假,因此会被选中,从而产生A B
。
答案 1 :(得分:0)
它的专业化;编译器选择最专业的版本。
暂时忽略bool
的默认值(S<2>
中的S<2, true>
和S<3>
中的S<3, false>
转换;你有
template <unsigned N, bool>
struct S
{ /* something */};
template <unsigned N>
struct S<N, true>
{ /* something */};
关于第二个(bool
one)模板参数,第一个是中性的;所以匹配S<2, true>
和S<3, false>
。
第二个要求第二个模板参数为true
,因此仅匹配S<2, true>
。并且比第一个模板更专业,因为第二个模板的每个匹配也匹配第一个模板,但是第一个模板的匹配不匹配第二个模板(S<3, false>
,例子)。
对于S<3, false>
,编译器只找到匹配的模板(第一个),所以选择第一个。
对于S<2, true>
,编译器会找到最匹配和最具特色的模板(C ++规则),即第二个模板。
当您更改true
false
时,S<3, false>
匹配两个版本,因此选择第二个版本,S<2, true>
仅匹配第一个版本。< / p>