模板推导中的偏序过程是什么
阅读C++11标准我无法完全理解以下语句的含义.非常欢迎示例.
Reading the C++11 standard I can't fully understand the meaning of the following statement. Example are very welcome.
使用两组类型来确定偏序.对于每个在所涉及的模板中,有原始函数类型和转换的函数类型.[注:转换类型的创建在 14.5.6.2 中描述.― 尾注] 演绎过程使用转换类型作为参数模板和原始类型其他模板作为参数模板.这个过程做两次对于偏序比较中涉及的每种类型:一次使用转换后的 template-1 作为参数模板,template-2 作为参数模板并再次使用转换后的模板 2 作为参数模板和模板1作为参数模板
-- N3242 14.8.2.4.2
Two sets of types are used to determine the partial ordering. For each of the templates involved there is the original function type and the transformed function type. [Note: The creation of the transformed type is described in 14.5.6.2. ― end note ] The deduction process uses the transformed type as the argument template and the original type of the other template as the parameter template. This process is done twice for each type involved in the partial ordering comparison: once using the transformed template-1 as the argument template and template-2 as the parameter template and again using the transformed template-2 as the argument template and template-1 as the parameter template
-- N3242 14.8.2.4.2
推荐答案
虽然 Xeo 给了 评论中的一个很好的描述,我会试着用一个工作示例一步一步地解释.
While Xeo gave a pretty good description in the comments, I will try to give a step-by-step explanation with a working example.
首先,你引用的段落的第一句话是:
First of all, the first sentence from the paragraph you quoted says:
对于每个涉及的模板,都有原始函数类型和转换后的函数类型.[...]
For each of the templates involved there is the original function type and the transformed function type. [...]
等等,这个转换函数类型"是什么?第 14.5.6.2/3 段解释说:
Hold on, what is this "transformed function type"? Paragraph 14.5.6.2/3 explains that:
生成转换后的模板,对于每个类型、非类型或模板模板参数(包括其模板参数包(14.5.3))分别合成一个唯一的类型、值或类模板并将其替换为模板的函数类型中每次出现的该参数 [...]
To produce the transformed template, for each type, non-type, or template template parameter (including template parameter packs (14.5.3) thereof) synthesize a unique type, value, or class template respectively and substitute it for each occurrence of that parameter in the function type of the template [...]
这种形式化的描述可能听起来晦涩难懂,但实际上在实践中非常简单.我们以这个函数模板为例:
This formal description may sound obscure, but it is actually very simple in practice. Let's take this function template as an example:
template<typename T, typename U>
void foo(T, U) // #1
现在由于 T
和 U
是类型参数,上面的段落要求我们为 T
选择一个相应的类型参数(无论如何)并在出现 T
的函数签名中的任何地方替换它,然后对 U
执行相同的操作.
Now since T
and U
are type parameters, the above paragraph is asking us to pick a corresponding type argument for T
(whatever) and substitute it everywhere in the function signature where T
appears, then to do the same for U
.
现在合成一个独特的类型"意味着你必须选择一个你没有在其他任何地方使用过的虚构类型,我们可以称之为P1
(然后为 U
选择一个 P2
),但这会使我们的讨论变得毫无意义.
Now "synthesizing a unique type" means that you have to pick a fictitious type you haven't used anywhere else, and we could call that P1
(and then pick a P2
for U
), but that would make our discussion uselessly formal.
让我们简化一下,为 T
选择 int
,为 U
选择 bool
- 我们没有使用这些类型在其他任何地方,因此就我们的目的而言,它们与 P1
和 P2
一样好.
Let's just simplify things and pick int
for T
and bool
for U
- we're not using those types anywhere else, so for our purposes, they are just as good as P1
and P2
.
所以在转换之后,我们有:
So after the transformation, we have:
void foo(int, bool) // #1b
这是我们原始 foo()
函数模板的转换后的函数类型.
This is the transformed function type for our original foo()
function template.
那么让我们继续解释您引用的段落.第二句说:
So let's continue interpreting the paragraph you quoted. The second sentence says:
推导过程使用转换后的类型作为参数模板,将其他模板的原始类型作为参数模板.[...]
The deduction process uses the transformed type as the argument template and the original type of the other template as the parameter template. [...]
等等,什么其他模板"?到目前为止,我们只有一个 foo()
的重载.是的,但是为了在函数模板之间建立排序,我们至少需要其中两个,所以我们最好创建第二个.让我们使用:
Wait, what "other template"? We only have one overload of foo()
so far. Right, but for the purpose of establishing an ordering between function templates, we need at least two of them, so we'd better create a second one. Let's use:
template<typename T>
void foo(T const*, X<T>) // #2
其中 X
是我们的某个类模板.
Where X
is some class template of ours.
现在第二个函数模板怎么样?啊,是的,我们需要对 foo()
的第一个重载做与之前相同的操作并转换它:再次,让我们为 T
选择一些类型参数,然后到处替换 T
.这次我会选择 char
(在这个例子中我们没有在其他任何地方使用它,所以它和一些虚构的 P3
一样好):
Now what with this second function template? Ah, yes, we need to do the same we previously did for the first overload of foo()
and transform it: so again, let's pick some type argument for T
and replace T
everywhere. I'll pick char
this time (we aren't using it anywhere else in this example, so that's as good as some fictitious P3
):
void foo(char const*, X<char>) #2b
太好了,现在他有两个函数模板和对应的转换函数类型.那么如何判断#1
是否比#2
更专业,反之亦然?
Great, now he have two function templates and the corresponding transformed function types. So how to determine whether #1
is more specialized than #2
or vice versa?
我们从上面的句子中知道,原始模板和它们转换后的函数类型必须以某种方式匹配.但是如何?这就是第三句话的解释:
What we know from the above sentence is that the original templates and their transformed function types must be matched somehow. But how? That's what the third sentence explains:
这个过程对偏序比较中涉及的每个类型进行两次:一次使用转换后的 template-1 作为参数模板和 template-2 作为参数模板,再次使用转换后的 template-2 作为参数模板和template-1 作为参数模板
This process is done twice for each type involved in the partial ordering comparison: once using the transformed template-1 as the argument template and template-2 as the parameter template and again using the transformed template-2 as the argument template and template-1 as the parameter template
所以基本上第一个模板(#1b
)的转换函数类型要与原始第二个模板的函数类型匹配模板(#2
).当然反过来,第二个模板(#2b
)的转换函数类型将与原始的函数类型匹配 第一个模板(#1
).
So basically the transformed function type of the first template (#1b
) is to be matched against the function type of the original second template (#2
). And of course the other way round, the transformed function type of the second second template (#2b
) is to be matched against the function type of the original first template (#1
).
如果匹配在一个方向上成功但在另一个方向上失败,那么我们就会知道其中一个模板比另一个更专业.否则,两者都不是更专业.
If matching will succeed in one direction but not in the other, then we will know that one of the templates is more specialized than the other. Otherwise, neither is more specialized.
让我们开始吧.首先,我们必须匹配:
Let's start. First of all, we will have to match:
void foo(int, bool) // #1b
反对:
template<typename T>
void foo(T const*, X<T>) // #2
有没有一种方法可以对 T
进行类型推导,使 T const*
完全变成 int
和 X
变成了 bool
吗?(实际上,完全匹配不是必需的,但此规则确实很少有例外,它们与说明偏序机制的目的无关,因此我们将忽略它们).
Is there a way we can perform type deduction on T
so that T const*
becomes exactly int
and X<T>
becomes exactly bool
? (actually, an exact match is not necessary, but there are really few exceptions to this rule and they are not relevant for the purpose of illustrating the partial ordering mechanism, so we'll ignore them).
几乎没有.因此,让我们尝试以相反的方式进行匹配.我们应该匹配:
Hardly. So let's try matching the other way round. We should match:
void foo(char const*, X<char>) // #2b
反对:
template<typename T, typename U>
void foo(T, U) // #1
我们能否在这里推导出 T
和 U
以生成 char const*
和 X
的精确匹配代码>,分别是?当然!这是微不足道的.我们只选择 T = char const*
和 U = X
.
Can we deduce T
and U
here to produce an exact match for char const*
and X<char>
, respectively? Sure! It's trivial. We just pick T = char const*
and U = X<char>
.
所以我们发现我们第一次重载 foo()
(#1b
) 的转换后的函数类型不能与我们第二次重载的原始函数模板匹配foo()
(#2
);另一方面,第二个重载(#2b
)的转换函数类型可以与第一个重载的原始函数模板(#1
).
So we found out that the transformed function type of our first overload of foo()
(#1b
) cannot be matched against the original function template of our second overload of foo()
(#2
); on the other hand, the transformed function type of the second overload (#2b
) can be matched against the original function template of the first overload (#1
).
结论?foo()
的第二个重载比第一个更特殊.
Conclusion? The second overload of foo()
is more specialized than the first one.
要选择一个反例,请考虑以下两个函数模板:
To pick a counter-example, consider these two function templates:
template<typename T, typename U>
void bar(X<T>, U)
template<typename T, typename U>
void bar(U, T const*)
哪个重载比另一个更专业?我不会再经历整个过程,但你可以这样做,这应该让你相信在任何一个方向都不能产生匹配,因为第一个重载比第二个更专业,涉及第一个参数,但是第二个参数比第一个参数更专业.
Which overload is more specialized than the other? I won't go through the whole procedure again, but you can do it, and that should convince you that a match cannot be produced in either direction, since the first overload is more specialized than the second one for what concerns the first parameter, but the second one is more specialized than the first one for what concerns the second parameter.
结论?没有一个函数模板比??另一个更专业.
Conclusion? Neither function template is more specialized than the other.
现在在这个解释中,我忽略了标准中的很多细节、规则的例外和隐秘的段落,但你引用的段落中概述的机制确实是这个.
Now in this explanation I have ignored a lot of details, exceptions to the rules, and cryptic passages in the Standard, but the mechanism outlined in the paragraph you quoted is indeed this one.
另请注意,上面概述的相同机制用于在 class 模板的部分特化之间建立更特化"排序,方法是首先创建一个为每个专业化关联的、虚构的函数模板,然后通过本答案中描述的算法对这些函数模板进行排序.
Also notice, that the same mechanism outlined above is used to establish a "more-specialized-than" ordering between partial specializations of a class template by first creating an associated, fictitious function template for each specialization, and then ordering those function templates through the algorithm described in this answer.
这是由 C++11 标准的第 14.5.5.2/1 段指定的:
This is specified by paragraph 14.5.5.2/1 of the C++11 Standard:
对于两个类模板部分特化,第一个至少和第二个一样特化,如果,给定重写为两个函数模板后,第一个函数模板至少与第二个函数模板一样专业根据函数模板的排序规则(14.5.6.2):
For two class template partial specializations, the first is at least as specialized as the second if, given the following rewrite to two function templates, the first function template is at least as specialized as the second according to the ordering rules for function templates (14.5.6.2):
――第一个函数模板与第一个偏特化具有相同的模板参数,并且有单个函数参数,其类型是具有模板参数的类模板特化第一部分专业化,以及
― the first function template has the same template parameters as the first partial specialization and has a single function parameter whose type is a class template specialization with the template arguments of the first partial specialization, and
――第二个函数模板与第二个偏特化具有相同的模板参数并且有一个函数参数,其类型是具有模板的类模板特化第二部分特化的参数.
― the second function template has the same template parameters as the second partial specialization and has a single function parameter whose type is a class template specialization with the template arguments of the second partial specialization.
希望这有帮助.
相关文章