什么时候模板比另一个更专业?'和''或'与逻辑混淆.

Joh*_*itb 13 c++ partial-ordering c++11

在C++ 11草案的14.8.2.4p10中,写了

如果对于每种类型被认为是给定的模板至少对所有类型都是专用的,并且对于某些类型更专用,而另一个模板对于任何类型都不是更专用的,或者至少不是对任何类型的专用,那么给定的模板比其他模板更专业.

为什么"或者至少不是任何类型的专业"?据我所知,如果我们有一个类型列表

T1, T2, T3
U1, U2, U3
Run Code Online (Sandbox Code Playgroud)

如果所有Ts至少都是专业的,有些则更专业.并且没有一个人更专业,那么在我看来,从逻辑上讲,整个T的集合比U集合更专业.为什么当时没有一个人至少比相应的Ts更专业?

Joh*_*itb 7

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


我终于想出了如何阅读有问题的段落.我在下面发了一个项目符号

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

  • 更专业的一些类型和另一个模板不是更专业的任何类型,或
  • {另一个模板}至少不适用于任何类型,

那么给定的模板比其他模板更专业.

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

template<typename T> void f(T*);
template<typename T> void f(T);
Run Code Online (Sandbox Code Playgroud)

请注意,第一个模板的参数至少与第二个模板一样专用,但未定义为"更专业" - 该术语仅适用于两个参数均为参考且某些条件适用的情况(参见第14.8节第9段). 2.4).这些规则显然符合任何正式的订购法律.第二个模板至少与第一个模板不同.这意味着第二颗子弹适用,而不是第一颗子弹.


And*_*owl 6

这个答案是基于对标准段落的抽象语法树的错误解析."返回标准"部分中假设的条件分组结果不是预期的.预期的分组是Johannes Schaub在他的回答中所表明的.


为什么当时没有一个人至少比相应的Ts更专业?

我同意你的看法,第二部分(实际上,整个第二部分)是多余的.


一些参考词汇:

让我们对逻辑有一些乐趣,并在两个模板之间引入一对相应参数的3个基本关系:

  • 更专业的比:对参数TiUi分别,一个模板匹配等,但反之亦然.我会说明这一点Ti < Ui;
  • 同样专业:对于参数TiUi分别,一个模板匹配另一个,反之亦然.我会说明这一点Ti == Ui;
  • 专业化 - 无法比较:对于参数TiUi分别,没有一个模板与特定参数的另一个匹配.我会说明这一点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
Run Code Online (Sandbox Code Playgroud)

对于第一个参数,(1)比(<)(2)更专业; 对于第二个参数,(1)同样专门用作(或" 专门用作 ",==)(2); 对于第三个参数,(1)是特化 - 与(~)(2)无法比较.

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

  • 模板(1)至少与各个参数的另一个模板(2)一样专用,Ti并且Ui(Ti < Ui)(Ti == Ui)(即,(1)比(2)更专用或(1)与(2)一样专用时).在上面的例子,因此,T1 <= U1,T2 <= U2,和U2 <= T2.

回到标准:

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

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

(给定的模板至少对所有类型都是专用的,对某些类型的集合更专用)

                                 AND 
Run Code Online (Sandbox Code Playgroud)

(另一个模板对于任何类型都不是更专业的

                                 OR
Run Code Online (Sandbox Code Playgroud)

至少不是任何类型的专业)

给定两个模板相对于参数类型的相应序列进行排序T1, ..., TnU1, ..., Un,条件(A):

[...]给定的模板至少对所有类型都是专门的,对于某些类型的集合更专业[...]

意味着每一个i = 1..n,Ti <= Ui以及一些jS IN 1..n,它适用更严格的条件Tj < Uj.删除索引i,这意味着对于每个参数:

(T < U) || (T == U) // (A)
Run Code Online (Sandbox Code Playgroud)

该条件与另一个条件(B)逻辑连接("和"),这又是两个子条件(B1)和(B2)的逻辑分离("或").让我们开始检查子条件(B1):

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

这意味着,对于任何i情况,从来都不是这样Ui < Ti,这意味着:

  • TiUi(Ti < Ui)更专业; 要么
  • Ti并且Ui同样专业(Ui == Ti); 要么
  • Ti并且Ui是专业化 - 无与伦比的(Ui ~ Ti):

更正式的:

!(U < T) <==> (T < U) || (T == U) || (T ~ U) // (B1)
Run Code Online (Sandbox Code Playgroud)

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

[...]至少不是任何类型的专业[...]

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

!(U <= T) <==> !((U == T) || (U < T)) ==> !(U == T) && !(U < T)
Run Code Online (Sandbox Code Playgroud)

因此,换句话说,TU没有相等的专业,也不U是比更加专业化T.因此,剩下的唯一可能性是:

(T < U) || (T ~ U) // (B2)
Run Code Online (Sandbox Code Playgroud)

现在很明显(B2)暗示(B1),因为(B2)更具限制性.因此,它们的析取(B)将与(B1)重合,而(B2)是多余的:

(T < U) || (T ~ U) || (T == U) // (B)
Run Code Online (Sandbox Code Playgroud)

但这里显而易见的是(A)比(B)更严格,因此(A)和(B)的结合等同于(A).


结论:

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