C ++模板选择 [英] C++ template selection

查看:95
本文介绍了C ++模板选择的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出以下代码:

#include <memory>
#include <iostream>

using namespace std;

template<typename T>
void test(T & value) {
  cout << "most generic" << endl;
}

template<typename T>
void test(shared_ptr<T> & value) {
  cout << "shared_ptr" << endl;
}

class A {};

int main(int argc, char ** argv) {
  A a;
  shared_ptr<A> p(new A());
  test(a);
  test(p);
  return 0;
}

为什么打来电话

test(p)

实例化第二种形式的用T = A进行测试,而不是抱怨它不能区分两个签名?

instantiating the second form of test with T = A instead of complaining that it cannot distinguish between the two signatures ?

推荐答案

因为即使它们都是可行的选择对于重载解决方案,第二个功能模板比第一个功能模板更专业化。

Because even though they are both viable choices for overload resolution, the second function template is more specialized than the first one.

根据C ++第13.3.3 / 1段11标准:

Per Paragraph 13.3.3/1 of the C++11 Standard:


[...]给出这些定义,将可行的函数F1定义为更好 >函数,而不是另一个可行的函数
F2,如果对于所有参数i,ICSi(F1)的转换顺序都不比ICSi(F2)差,然后

[...] Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then

—对于某些参数j,ICSj(F1)比ICSj(F2)更好,或者,否则,

— for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2), or, if not that,

—上下文是用户的初始化定义的转化(请参见8.5, 13.3.1.5和13.3.1.6)以及从F1的返回类型到目标类型的
标准转换序列(即,正在初始化的
实体的类型)比标准转换序列,从
返回F2到目标类型。 [...]或,否则,

— the context is an initialization by user-defined conversion (see 8.5, 13.3.1.5, and 13.3.1.6) and the standard conversion sequence from the return type of F1 to the destination type (i.e., the type of the entity being initialized) is a better conversion sequence than the standard conversion sequence from the return type of F2 to the destination type. [...] or, if not that,

— F1是非模板函数,F2是函数模板特化,或者,否则,

— F1 is a non-template function and F2 is a function template specialization, or, if not that,

-F1和F2是功能模板特化,并且 F1的功能模板比F2的模板更专业化
14.5.6.2。中描述的部分排序规则。

— F1 and F2 are function template specializations, and the function template for F1 is more specialized than the template for F2 according to the partial ordering rules described in 14.5.6.2.

第14.5.6.2节接着说说如何确定一个函数模板比​​另一个模板更专业功能模板。特别是,每14.5.6.2/2:

§ 14.5.6.2 then says how a function template is determined to be more specialized than another function template. In particular, per 14.5.6.2/2:


部分排序通过转换$ b来选择两个功能模板中的哪个比另一个更专业$ b依次转换每个模板(请参阅下一段),并使用函数
类型执行模板参数推导。推导过程确定其中一个模板是否比另一个模板更专业。如果
是这样,则更专业的模板是部分排序过程选择的模板。

Partial ordering selects which of two function templates is more specialized than the other by transforming each template in turn (see next paragraph) and performing template argument deduction using the function type. The deduction process determines whether one of the templates is more specialized than the other. If so, the more specialized template is the one chosen by the partial ordering process.

标准中的形式定义可以很难破译,但是它们的复杂性通常意味着大多数情况下明确地使语言表现得像我们自然期望的

Formal definitions in the Standard can be pretty hard to decipher, but their complexity is normally meant to unambiguously make the language behave like we would naturally expect in most situations.

我们对您提供的重载的直观期望是,当参数为时,应选择接受 std :: shared_ptr< T> 的重载。 std :: shared_ptr< int> 类型的,因为它似乎正在处理 std :: shared_ptr<> 专门针对对象,因此,它看起来比无限制的重载更好(更专业)。

The intuitive expectations we could have about the overloads you provide is that the one accepting a std::shared_ptr<T> should be selected when the argument is of type std::shared_ptr<int>, because it appears to be dealing with std::shared_ptr<> objects specifically and, therefore, it looks like a better (more specialized) candidate than the unconstrained overload.

翻译这种直观方法的正式过程对明确的规则的期望听起来可能很复杂,但是在我们的情况下遵循它并不是特别困难n,我们要确定此重载是否存在:

The formal procedure for translating this intuitive expectation into an unambiguous set of rules may sound complex, but following it is not particularly hard in our situation, where we want to determine if this overload:

template<typename T>
void f(std::shared_ptr<T>);

比这更专业:

template<typename U>
void f(U);

尽管在这种情况下,我们很容易根据直觉判断哪个更专业,编译器必须依赖算法,并且该算法必须在所有情况下都有效。

Although in this case it is easy for us to tell which one is more specialized just based on our intuition, a compiler must rely on an algorithm, and this algorithm must work in all situations.

在这种情况下,该机制如下:

In this case, the mechanism would go as follows:


  1. first 重载,将其模板参数 T 替换为类型参数( any 类型参数),例如 int ,并实例化相应的签名-函数参数的类型为 std :: shared_ptr< int> ;

  2. 是否总是有可能通过提供该类型的对象来调用 second 重载(在这种情况下, shared_ptr< int> )作为输入,并从中推断出类型 U

  3. 嗯,答案是 U 只会被推导为 std :: shared_ptr< int> ;

  4. 现在反过来:以 second 重载,将其模板参数 U 替换为任何类型参数,例如 bool ,并实例化相应的签名-函数参数的类型为 bool ;

  5. 是否通过提供该类型的对象( bool )并推断出类型,总是可以调用 first 重载T 来自它吗?

  6. 当然,这里的答案是。无法推断 T ,以致 std :: shared_ptr< T> 将匹配 bool ;

  7. 结论:第一个重载比第二个重载更为专业

  1. Take the first overload, substitute its template parameter T for a type argument (any type argument), for instance int, and instantiate the corresponding signature - the function parameter would have type std::shared_ptr<int>;
  2. Is it always possible to call the second overload by providing an object of that type (shared_ptr<int> in this case) as its input, and deduce the type U from it?
  3. Well, the answer is Yes. U will just be deduced to be std::shared_ptr<int>;
  4. The other way round now: Take the second overload, substitute its template parameter U for any type argument, for instance bool, and instantiate the corresponding signature - the function parameter would have type bool;
  5. Is it always possible to call the first overload by providing an object of that type (bool) as its argument and deduce the type T from it?
  6. The answer here is No, of course. There is no way to deduce T so that std::shared_ptr<T> would match bool;
  7. Conclusion: The first overload is more specialized than the second.

当然,当存在多个模板参数和多个函数参数时,事情会变得稍微复杂一些,但是机制几乎相同。

Of course, things get slightly more complicated when there is more than one template parameter and more than one function parameter, but the mechanism is pretty much the same.

这篇关于C ++模板选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆