问题描述
我阅读了关于c ++ 11标准,但是不能很好地理解下面的示例是非常优选的。
Xeo给予,我将尝试用一个工作示例给出一个逐步的解释。
首先,你引用段落的第一句话:
继续,这是什么转换函数类型第14.5.6.2/3段说明:
这种形式描述可能听起来很模糊,但实际上其实很简单。让我们以这个功能模板为例:
template< typename T,typename U>
void foo(T,U)//#1
c> T 和 U 是类型参数,上述段落要求我们为 T (无论如何),并且在 T 出现的函数签名中的任何地方替换它,然后对 U 。
现在合成唯一类型意味着您必须选择一个虚拟类型, ,我们可以调用 P1 (然后为 U $>选择 P2 c $ c>),但这将使我们的讨论无用地正式。
让我们简化一下,为 T 选择 int 和 bool for U - 我们不会在其他地方使用这些类型,因此为了我们的目的,好如 P1 和 P2 。
转换后,我们有:
void foo int,bool)//#1b
这是我们原来的转换后的函数类型 foo()函数模板。
所以让我们继续解释你引用的段落。第二句说:
等待,其他模板到目前为止,我们只有一个 foo()的重载。对,但是为了在函数模板之间建立顺序,我们至少需要两个函数模板,所以我们最好再创建一个。让我们使用:
template< typename T>
void foo(T const *,X< T>)//#2
X 是我们的一些类模板。
现在这个第二个函数模板是什么?嗯,是的,我们需要做与之前对 foo()的第一次重载所做的相同的操作,然后进行转换:再次,让我们为 T 并替换 T 。我将选择 char 这一次(我们不在这个例子中的任何地方使用它,所以这和一些虚拟的 P3 ):
void foo(char const *,X< char>)#2b
很好,现在他有两个函数模板和相应的转换函数类型。那么如何确定#1 是否比#2 更专业,反之亦然?
从上面的句子我们知道,原始模板和他们转换的函数类型必须以某种方式匹配。但是怎么样?这是第三句解释的:
因此,基本上第一个模板(#1b )的转换后的函数类型要与原始第二个模板(#2 )。当然,另一方面,第二个第二个模板(#2b )的转换函数类型要与函数类型
如果匹配将成功,则会在第一个模板中创建 第一个模板(#1 方向,但不在另一个,那么我们将知道其中一个模板比另一个更专业。否则,两者都不专业。
让我们开始吧。首先,我们必须匹配:
void foo(int,bool)//#1b
反对:
template< typename T>
void foo(T const *,X< T>)//#2
有一种方法我们可以在 T 上执行类型推导,使得 T const * 正好成为 int 和 X< T> 完全变为 bool ? (实际上,并不需要一个 exact 匹配,但是这个规则只有少数例外,它们与说明部分排序机制的目的不相关,所以我们将忽略它们。)
很难。所以,让我们尝试匹配另一种方式。我们应该匹配:
void foo(char const *,X< char>)//#2b
反对:
;类型名称T,类型名称U>
void foo(T,U)//#1
我们可以推导出 T 和 U 这里为 char const * X< char> 当然!这是微不足道的。我们只需选择 T = char const * 和 U = X 。
所以我们发现我们第一个重载 foo()的变换函数类型(#1b )不能与 foo()(#2 )的第二个重载的原始函数模板匹配;另一方面,第二重载的转换函数类型(#2b )可以与第一重载的原始函数模板匹配#1 )。
结论? foo()的第二个重载比第一个重载。
要选择一个反例,考虑这两个功能模板:
template< typename T,typename U>
void bar(X< T> U)
template< typename T,typename U>
void bar(U,T const *)
?我不会再经历整个过程,但你可以做到,这应该说服你不能产生任何方向的匹配,因为第一个重载比第二个更关注第一个参数,但第二个比第一个更专门,关于第二个参数。
结论?
现在在这个解释中,我忽略了很多细节,规则的例外,以及标准中的隐秘段落,但是,您引用的段落中列出的机制确实是这一个。
还要注意,上述同样的机制用于建立一个通过首先为每个专业化创建相关联的虚构功能模板,然后通过本答案中描述的算法对这些功能模板进行排序,从而在类模板的部分专业化之间进行排序。 p>
这是由C ++ 11标准的第14.5.5.2/1节指定的:
希望这有帮助。
I read about the c++11 standard but can't understand well the meanning of the following.example are very preferred.
解决方案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:
Hold on, what is this "transformed function type"? Paragraph 14.5.6.2/3 explains that:
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) // #1Now 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.
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.
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) // #1bThis is the transformed function type for our original foo() function template.
So let's continue interpreting the paragraph you quoted. The second sentence says:
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>) // #2Where X is some class template of ours.
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>) #2bGreat, 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:
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) // #1bAgainst:
template<typename T> void foo(T const*, X<T>) // #2Is 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>) // #2bAgainst:
template<typename T, typename U> void foo(T, U) // #1Can 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>.
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).
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.
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.
This is specified by paragraph 14.5.5.2/1 of the C++11 Standard:
Hope this helped.
这篇关于什么是模板扣除中的部分排序过程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!