14

在 C++11 草案的 14.8.2.4p10 中,有这样写

如果对于每个被考虑的类型,一个给定的模板至少对所有类型都是专门化的,并且对某些类型集更专门化,而另一个模板对任何类型都没有更专门化,或者至少对任何类型都没有专门化,那么给定模板比其他模板更专业。

为什么有一个“或至少不像任何类型那样专门化”?据我所知,如果我们有一个类型列表

T1, T2, T3
U1, U2, U3

如果所有 T 至少都一样专业化,而有些则更专业化。并且没有一个 U 比 U 更特化,那么在我看来,从逻辑上讲,T 的集合作为一个整体比 U 的集合更特化。当我们没有一个至少比相应的 T 专业化时,为什么会有提到的后备?

4

2 回答 2

7

更新:现在已将其添加为官方 C++ 问题


我终于弄清楚了如何阅读有问题的段落。下面我已经打了它

如果对于被考虑的每种类型,给定模板至少对所有类型都是专用的,并且

  • 对某些类型更专业化,而另一个模板对任何类型都没有更专业化,或者
  • {the other template} 至少不适合任何类型,

那么给定的模板比另一个模板更专业。

这样,下面的第一个模板也比第二个模板更专业

template<typename T> void f(T*);
template<typename T> void f(T);

请注意,第一个模板的参数至少与第二个模板一样特化,但并未定义为“更特化”——该术语仅适用于两个参数都是引用且适用某些条件的情况(参见 14.8.9 的第 9 段。 2.4) 。这些规则显然并不意味着遵循任何正式的订购法。第二个模板至少不像第一个模板那样专门化。这意味着第二个项目符号适用,而不是第一个项目符号。

于 2013-03-29T20:24:08.557 回答
6

此答案基于对标准段落的抽象语法树的错误解析。“回到标准”部分中假设的条件分组结果不是预期的。预期的分组是 Johannes Schaub 在他的回答中显示的分组。


当我们没有一个至少比相应的 T 专业化时,为什么会有提到的后备?

我同意你的观点,第二部分(实际上是整个第二个条件)是多余的。


一些参考词汇:

让我们玩一些逻辑的乐趣,并为一对对应的参数介绍两个模板之间的 3 个基本关系:

  • : 对于参数TiUi分别更专业,一个模板匹配另一个模板,反之则不然。我将其表示为Ti < Ui
  • 同样专业化:对于参数TiUi分别,一个模板匹配另一个模板反之亦然。我将其表示为Ti == Ui
  • Specialization-incomparable:对于参数Ti和,对于特定参数Ui没有一个模板与另一个模板匹配。我将其表示为T1 ~ U1

例如,在下面的代码片段中:

template<typename X> struct A { };
template<typename X> struct B { };

template<typename X> void foo(A<X>, X, A<X>) { } // 1
template<typename X> void foo(X,    X, B<X>) { } // 2

对于第一个参数,(1) 比 ( <) (2) 更专业;对于第二个参数, (1) 与 (或 "", ==) (2) 一样特化;对于第三个参数,(1) 与 ( ~) (2) 是特化不可比的。

现在让我们定义一个派生关系:

  • 对于各个参数,模板(1)至少与另一个模板(2)一样特化Ti,并且Ui(Ti < Ui)或时(Ti == Ui),即当(1) 比(2) 更特化时,或者(1) 与(2) 一样特化。因此,在上面的示例中,T1 <= U1T2 <= U2U2 <= T2

回到标准:

在几个括号的帮助下,上面的引用变为 (A && (B1 || B2)):

[...] 对于正在考虑的每种类型:

一个给定的模板至少对所有类型都是专门化的,并且对某些类型更加专门化

                                 AND 

另一个模板不是更专业于任何类型

                                 OR

至少不适合任何类型

T1, ..., Tn给定两个要根据参数类型和的相应序列排序的模板U1, ..., Un,条件 (A):

[...] 一个给定的模板至少对所有类型都是专用的,并且对某些类型集更专业 [...]

意味着对于每个i = 1..n,Ti <= Ui和某些js in 1..n,它应用更严格的条件Tj < Uj. 删除 index i,这意味着对于每个参数:

(T < U) || (T == U) // (A)

该条件与另一个条件 (B) 进行逻辑合取 (“and”),而后者又是两个子条件 (B1) 和 (B2) 的逻辑合取 (“or”)。让我们开始检查子条件(B1):

[...] 另一个模板不是更专业于任何类型 [...]

这意味着对于 any i,永远不会是 that Ui < Ti,这意味着:

  • TiUi( Ti < Ui) 更专业;或者
  • Ti并且Ui同样专业化(Ui == Ti);或者
  • Ti并且Ui是专业化不可比的 ( Ui ~ Ti):

更正式地说:

!(U < T) <==> (T < U) || (T == U) || (T ~ U) // (B1)

现在让我们看看第二个子条件 (B2),它与 ​​(B1) 进行逻辑分离:

[...] 至少不适合任何类型 [...]

这是 的否定U <= T,这意味着:

!(U <= T) <==> !((U == T) || (U < T)) ==> !(U == T) && !(U < T)

换句话说,TandU不是同等专业的,也不U是比 更专业的T。因此,剩下的唯一可能是:

(T < U) || (T ~ U) // (B2)

现在很明显,(B2) 蕴含 (B1),因为 (B2) 更具限制性。因此,它们的析取 (B) 将与 (B1) 重合,并且 (B2) 是多余的:

(T < U) || (T ~ U) || (T == U) // (B)

但是这里同样明显的是(A)比(B)更严格,所以(A)和(B)的合取等价于(A)。


结论:

整个条件(B)是多余的。

于 2013-03-29T15:51:52.660 回答