2012-04-03 64 views
3

我很难理解正式订购规则是如何工作的,正如D. Vandevoorde和N. M. Josuttis所着的“C++模板,完整指南”一书第12章所述。在这本书的第188页,作者给出用来决定哪两个可行函数模板是更加专业化的以下情形:C++模板正式订购规则

从我们通过如前所述更换模板参数合成参数类型的两个列表这两个模板:(A1)(A2*)(其中A1A2是独特的组成类型)。很明显,通过用A2*代替T,第二个参数类型列表中的第一个模板被扣除。但是,无法使第二个模板的T*与第一个列表中的非指针类型A1匹配。因此,我们正式得出结论,第二个模板比第一个模板更专业。

我想了解一些例子。

编辑

我相信,在以上报价提到两个函数模板

template<typename T> 
int f(T) 
{ 
    return 1; 
} 

template<typename T> 
int f(T*) 
{ 
    return 2; 
} 
+0

我不明白为什么'T'是第一个非指针类型。为什么'T'不能'int *'? – 2012-04-03 12:02:25

+0

@SethCarnegie会做。 – Olumide 2012-04-03 12:10:55

+0

'T'可能是'int *'的第一个,但第二个会被选中,因为'T = int',它更专用。基本上,第一个只能选择非指针“T”。 – 2012-04-03 12:34:03

回答

5

规则有点难以解释比使用。这个想法是,如果一个模板比另一个模板更专业化,那么这个更专门化的可能实例化集合就是这个不太专业化实例化的一个严格子集。

也就是说,可以用作更专业的参数的每种类型也可以用作不那么专业化的参数,并且至少有一种类型可以用于不太专业化的不能使用的类型与更专业。

鉴于两个模板:

template <typename A> void f(A); // [1] 
template <typename B> void f(B*); // [2] 

问题解决是其中哪一个更通用(即可以采取的参数的数量更多)。标准中的整个描述是根据用于AB的合成独特类型完成的,但是我们可以用不太精确的方式来手动解决问题。如果我们找到一个与第二个模板参数匹配的类型X,那么第二个模板的实例将看起来像void f(X*)(除了它是模板的事实之外)。现在,模板[1]能用于生成等效函数吗?是的,通过在类型扣除中制作A == X*。我们可以在相反的方向吗?假设我们找到一个类型为Y的实例,我们可以实例化第一个模板,我们得到void f(Y)。第二个模板可以匹配这个呼叫吗?不,只适用于指针类型的子集,前面的语句可以保留。因为对于第二个模板的每个有效实例,我们也可以实例化第一个模板,但是第一个模板的一些实例化不会是有效的实例化第二。

举一个实际的例子,f(char*)可以被两个模板匹配,但f(5)只能被第一个匹配。在合成类型方面奇怪的解释的原因是一个例子不能保证顺序,它必须保持所有的类型。合成类型是类型的任何类型的代表。

+0

谢谢。请原谅我的慢,但我仍然有点不确定为什么第二个模板不能匹配第一个模板实例化的void f(Y)。 – Olumide 2012-04-03 13:51:32

+0

@Olumide:它可以*当且仅当*'Y'表示指向类型的指针。您需要在类型中查看'Y'中的所有'Y',而不是预先确定的类型,并且从那里类似于数学。 – 2012-04-03 14:28:06

+0

@Olumide:对于某个特定的类型'Y'(如'int *')你可以做到这一点是不够的,问题是是否有一个单独的类型'Y'(比如'int'),你不能。也就是说,'f(5)'可以被第一个模板与A == int匹配,但不能被第二个模板匹配(*没有类型'Y',所以'Y *'是'int' *) – 2012-04-03 14:43:09

0

我觉得作者的一点是,T IN的第一个模板可以匹配无论是A类型还是A *类型的指针,而第二个模板只能与指向A *类型的指针匹配,因此第二个模板更专用。