我很难理解正式排序规则的工作方式,如C ++模板,D。Vandevoorde和N. M. Josuttis的完整指南的第12章所述。在本书的第188页,作者给出了以下用于确定两个可行功能模板中哪一个更专业化的场景:
从这两个模板中,我们通过替换前面描述的模板参数来合成两个参数类型列表:
(A1)
和(A2*)
(其中A1
和A2
是唯一的类型)。显然,通过用A2*
代替T
,可以在第二个参数类型列表中扣除第一个模板。但是,无法使第二个模板的T*
与第一个列表中的非指针类型A1
匹配。因此,我们正式得出结论,第二个模板比第一个模板更专业。
我想要理解这个例子。
修改
我相信上面引用中提到的两个功能模板是
template<typename T>
int f(T)
{
return 1;
}
template<typename T>
int f(T*)
{
return 2;
}
答案 0 :(得分:5)
规则有点难以解释而不是使用。如果更专业化的可能实例化的集合是较不专业化的一组可能实例化的严格子集,则该想法是模板比另一模板更专业。
也就是说,每个可以用作更专业化的参数的类型也可以用作较不专业化的参数,并且至少有一种类型可以用于不太常用的类型,不能用于更专业。
给出两个模板:
template <typename A> void f( A ); // [1]
template <typename B> void f( B* ); // [2]
要解决的问题是其中一个更多是泛型(即可以采用更多参数)。标准中的整个描述是根据用于A
和B
的合成唯一类型完成的,但我们可以用不太精确的方式尝试用手挥动来解决。
假设我们找到与第二个模板参数匹配的类型X
,那么第二个模板的实例化将看起来像void f( X* )
(除了它是模板的事实)。现在,模板[1]可以用来生成等效函数吗?是的,通过在类型扣除中设置A == X*
。我们可以朝相反的方向做吗?假设我们找到了一个类型Y
,我们可以使用它来实例化第一个模板,我们得到void f( Y )
。第二个模板可以匹配此调用吗?不,仅适用于指针的类型子集,前一个语句可以容纳。
这意味着第二个模板更加专用,因为对于第二个模板的每个有效实例化,我们也可以实例化第一个模板,但是第一个模板的某些实例化不会是第二个有效的实例。
对于实际示例,f( char* )
可以与两个模板匹配,但f( 5 )
只能与第一个匹配。在合成类型方面进行奇怪解释的原因是单个示例不保证订单,它必须保留所有类型。合成类型是任何类型的代表。
答案 1 :(得分:0)
我认为作者的观点是第一个模板中的T可以匹配类型A和指向类型A *的指针,而第二个模板只能匹配指向类型A *的指针因此第二个模板更专业。