本文介绍了模板推导中的部分排序过程是什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

阅读C ++ 11标准后,我无法完全理解以下语句的含义。例子非常受欢迎。


解决方案

Xeo给出了,我将尝试通过一个工作示例进行逐步说明。



首先,您引用的段落中的第一句话说:

等等,这是什么 转换后的函数类型?第14.5.6.2/3段说明:

这种形式上的描述听起来有些晦涩,但实际上却很简单。让我们以该功能模板为例:

  template< typename T,typename U> 
void foo(T,U)//#1

由于 T 和 U 是类型参数,上面的段落要求我们为 T (无论如何)并将其替换为出现在 T 的函数签名中的所有位置,然后对 U



现在, 合成唯一类型意味着您必须选择一种在其他任何地方都没有使用过的虚拟类型,我们可以称其为 P1 (然后为 U c $ c>),但这会使我们的讨论变得毫无用处。



让我们简化一下,为 T 选择 int 和 bool 表示 U -我们不在其他任何地方使用这些类型,因此出于我们的目的,它们就像与 P1 和 P2 一样好。



因此,在转换之后,我们有:

  void foo( int,bool)//#1b 

这是原始<$ c $的转换函数类型c> foo()函数模板。



因此,让我们继续解释您引用的段落。第二句话说:

等等, 其他模板是什么?到目前为止,我们只有一个 foo()重载。是的,但是为了在功能模板之间建立顺序,我们至少需要两个模板,因此最好再创建一个。让我们使用:

  template< typename T> 
void foo(T const *,X< T>)//#2

其中 X 是我们的某些类模板。



现在第二个功能模板又如何呢?嗯,是的,我们需要像以前对 foo()的第一个重载所做的一样,并对其进行转换:所以再次,让我们为<$ c选择一个类型参数$ c> T 并随处替换 T 。这次我选择 char (在此示例中,我们未在其他任何地方使用它,因此,它与一些虚构的 P3 ):

  void foo(char const *,X< char>)#2b 

太好了,现在他有两个函数模板和相应的转换函数类型。那么,如何确定#1 是否比#2 更专业?反之亦然?



从以上句子我们知道,原始模板及其转换后的函数类型必须以某种方式进行匹配。但是如何?这就是第三句话的解释:

因此,基本上,第一个模板的 transformed 函数类型(#1b )要与原始第二个模板(#2 )。当然,反过来说,第二个第二个模板的 transformed 函数类型(#2b )将与原始第一个模板(#1 )。



如果匹配成功方向,而不是另一个方向,那么我们将知道其中一个模板比另一个模板更加专业。否则,两者都不是更专业。



开始吧。首先,我们必须匹配:

  void foo(int,bool)//#1b 

反对:

  template< typename T> 
void foo(T const *,X< T>)//#2

是有一种方法可以对 T 进行类型推导,使 T const * 准确地变为 int 和 X< T> 恰好是 bool ? (实际上,精确匹配不是必需的,但是该规则的例外情况很少,并且它们与说明部分排序机制无关,因此我们将忽略它们。) / p>

很难。因此,让我们尝试以另一种方式进行匹配。我们应该匹配:

  void foo(char const *,X< char>)//#2b 

反对:

  template< ; typename T,typename U> 
void foo(T,U)//#1

我们可以推断 T 和 U 在这里产生与 char const * 和分别 X< char> ?当然!这很简单。我们只选择 T = char const * 和 U = X< char> 。



因此我们发现 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 *)

哪个重载比另一个更专业?我不会再重复整个过程,但是您可以做到,这应该使您确信不能在任何方向上产生匹配,因为对于第一个参数,第一个重载比第二个重载更加专门,但是第二个参数在涉及第二个参数方面比第一个参数更加专业。



结论?



现在在这个解释中,我已经忽略了很多细节,规则的例外和标准中的神秘段落,但是



还要注意,上面概述的相同机制用于建立 更专业化的-首先,为每个专业化创建一个关联的虚构功能模板,然后通过此答案中描述的算法对这些功能模板进行排序。是在 class 模板的部分专业化之间进行排序。



这由C ++ 11标准的14.5.5.2/1段指定:

希望有帮助。


Reading the C++11 standard I can't fully understand the meaning of the following statement. Example are very welcome.

解决方案

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) // #1

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.

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) // #1b

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:

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

Where 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>) #2b

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:

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

Against:

template<typename T>
void foo(T const*, X<T>) // #2

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

Against:

template<typename T, typename U>
void foo(T, U) // #1

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>.

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.

这篇关于模板推导中的部分排序过程是什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 22:55