书C++模板:完整指南在第275页有一个例子,我无法绕过头脑.
引用书中的摘录......
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;
};
Run Code Online (Sandbox Code Playgroud)
不幸的是,部分专业化
Promotion<Array<T1>, Array<T2> >既不比专业化更专业化也更不专业化Promotion<T,T>.为避免模板选择模糊,添加了最后的部分特化.它比前两个部分特化中的任何一个都更专业.
为什么前两个模板不明确,为什么最后一个模板解决了模糊问题?当我尝试应用规则时,我或者无法弄清楚它是如何产生歧义的,或者如果我认为我有办法让它发生,我不知道为什么最后一个模板解决了问题.
j_r*_*ker 15
也许你的困惑源于这种关系"更专业而非"的关系.这是一个部分订单,而不是一个总订单 - 这意味着给定2个模板特化,并不总是一个比另一个更专业.
Anon的评论是正确的:假设第3个专业化不存在,后来你的代码中有:
Promotion<Array<double>, Array<double> > foo;
Run Code Online (Sandbox Code Playgroud)
(当然你可能实际上不会创建这个空结构类型的变量,但这只是强制实例化的最简单方法.)
鉴于此声明foo,将挑选前两个专业中的哪一个?
T = Array<double>.T1 = double,T2 = double.这两个专业都是适用的,所以我们需要确定哪个"比另一个更专业",并选择那个.怎么样?我们会说,X是不是更专业的Y,如果它是至少与专业的Y,但Y不是至少作为专业X.虽然看起来这只是围绕这个问题跳舞,但我们可以用一个聪明的规则来回答这个新问题:
X至少是一个专门的,Y如果不管我们分配给模板参数的X类型,结果类型总是可以匹配Y.
请注意,我们忘记了当前实例化中涉及的特定类型(在这种情况下double) - "至少是专门的"关系是部分特化本身的属性,并且不依赖于特定的实例化.
专业化1总是可以与专业化2相匹配吗?这个过程有点像代数.我们要求对于任何类型的T,我们可以发现类型T1和T2这样的:
Promotion<Array<T1>, Array<T2> > = Promotion<T, T>
Run Code Online (Sandbox Code Playgroud)
这意味着:
Array<T1> = T
Array<T2> = T
Run Code Online (Sandbox Code Playgroud)
所以答案是否定的.综观只是第一个隐含的结果,因为任何类型的T,在总体上是不可能找到一个类型T1,从而Array<T1>为同一类型T.(如果它的工作T正好是Array<long>如果,但并非T是int或char*或大多数其他类型的.)
反过来呢?专业化2总能与专业化1相匹配吗?我们要求对于任何类型的T1和T2,我们可以找到一个类型T,使得:
Promotion<T, T> = Promotion<Array<T1>, Array<T2> >
Run Code Online (Sandbox Code Playgroud)
这意味着:
T = Array<T1>
T = Array<T2>
Run Code Online (Sandbox Code Playgroud)
所以答案是否定的.考虑到任何类型的T1,它总是能够找到一个类型T,从而T是同一类型的Array<T1>-只是字面上T = Array<T1>.但在一般的其他类型的T2不受限的是一样的T1,如果它不是(例如,如果T1 = bool不过T2 = float),那么它是不可能找到一个类型T是相同的两个Array<T1>和Array<T2>.所以一般来说,找不到这样的类型是不可能的T.
在这种情况下,不仅专业化比其他专业化更专业化,甚至也不像其他专业化那样专业化.因此,如果需要实例化此模板类并且两个特化项都匹配 - 就像在Anon给出的示例中那样 - 没有办法选择"最佳".