引用书中的摘录……
template <typename T> class Promotion<T,T> { public: typdef T ResultT; }; template<typename T1,typename T2> class Promotion<Array<T1>,Array<T2> > { public: typedef Array<typename Promotion<T1,T2>::ResultT> ResultT; }; template<typename T> class Promotion<Array<T>,Array<T> > { public: typedef Array<typename Promotion<T,T>::ResultT> ResultT; };
Unfortunately,the partial specialization
Promotion<Array<T1>,Array<T2> >
is
neither more nor less specialized than the partial specialization
Promotion<T,T>
. To avoid template selection ambiguity,the last partial
specialization was added. It is more specialized than either of the prevIoUs
two partial specializations.
为什么前两个模板不明确,为什么最后一个模板解决了模糊问题?当我尝试应用规则时,我或者无法弄清楚它是如何产生歧义的,或者如果我认为我有办法让它发生,我不知道为什么最后一个模板解决了问题.
解决方法
Anon的评论是正确的:假设第3个专业化不存在,后来你的代码中有:
Promotion<Array<double>,Array<double> > foo;
(当然你可能实际上不会创建这个空结构类型的变量,但这只是强制实例化的最简单方法.)
鉴于这个foo的声明,将挑选前两个专业中的哪一个?
>专业化1适用,T = Array< double>.
>专业化2适用,T1 =双,T2 =双.
这两个专业都是适用的,所以我们需要确定哪个“比另一个更专业”,并选择那个.怎么样?我们会说X比Y更专业,如果它至少和Y一样专业,但Y至少不像X那样专业.虽然看起来这只是围绕这个问题跳舞,但我们有一个聪明的规则可以用来回答这个新问题:
如果不管我们为X的模板参数分配了什么类型,则X至少与Y一样专用,结果类型总是可以与Y匹配.
请注意,我们忘记了当前实例化中涉及的特定类型(在这种情况下,为double) – “至少是如此专用”关系是部分特化本身的属性,并且不依赖于特定的实例化.
专业化1总是可以与专业化2相匹配吗?这个过程有点像代数.我们要求对于任何类型T,我们可以找到类型T1和T2,这样:
Promotion<Array<T1>,Array<T2> > = Promotion<T,T>
这意味着:
Array<T1> = T Array<T2> = T
所以答案是否定的.仅考虑第一个隐含结果,给定任何类型T,通常不可能找到类型T1,使得阵列< T1>与T的类型相同(如果T恰好是Array< long>,它会起作用,但如果T是int或char *或大多数其他类型则不行.)
反过来呢?专业化2总能与专业化1相匹配吗?我们要求对于任何类型T1和T2,我们可以找到类型T,以便:
Promotion<T,T> = Promotion<Array<T1>,Array<T2> >
这意味着:
T = Array<T1> T = Array<T2>
所以答案是否定的.给定任何类型T1,总是可以找到类型T,使得T与Array< T1>的类型相同. – 只是字面上设置T = Array< T1>.但一般情况下,其他类型T2不会被限制为与T1相同,如果不是(例如,如果T1 = bool但T2 =浮动)那么就不可能找到类型T与Array< ; T1>和阵列< T2>.所以一般来说,找不到这样的类型是不可能的.
在这种情况下,不仅专业化比其他专业化更专业化,甚至也不像其他专业化那样专业化.因此,如果需要实例化此模板类并且两个特化项都匹配 – 就像在Anon给出的示例中那样 – 没有办法选择“最佳”.