C++模板选择

TiM*_*och 11 c++ templates c++11

给出以下代码:

#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;
}
Run Code Online (Sandbox Code Playgroud)

为什么打电话

test(p)
Run Code Online (Sandbox Code Playgroud)

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

And*_*owl 20

因为尽管它们都是重载决策的可行选择,但第二个功能模板比第一个功能模板更专业.

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

[...]鉴于这些定义,如果对于所有参数i,ICSi(F1)不是比ICSi(F2)更差的转换序列,则可行函数F1被定义为比另一个可行函数F2 更好的函数,然后

- 对于某些参数j,ICSj(F1)是比ICSj(F2)更好的转换序列,或者,如果不是,

- 上下文是由用户定义的转换初始化(见8.5,13.3.1.5和13.3.1.6)以及从返回类型F1到目标类型的标准转换序列(即,正在初始化的实体的类型)是一个比从F2的返回类型到目标类型的标准转换序列更好的转换序列.[...]或者,如果不是,

- F1是非模板函数,F2是函数模板特化,或者,如果不是,

- F1和F2是功能模板特化,根据14.5.6.2中描述的偏序规则,F1的功能模板比F2的模板更专业.

§14.5.6.2然后说明如何确定函数模板比​​另一个函数模板更专业.特别是,根据14.5.6.2/2:

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

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

我们对你提供的重载的直观期望是,std::shared_ptr<T>当参数是类型时std::shared_ptr<int>,应该选择接受a的那个,因为它似乎是std::shared_ptr<>专门处理对象,因此,它看起来像一个更好(更专业)的候选者而不是无约束的过载.

将这种直观的期望转化为明确的规则集的正式程序听起来可能很复杂,但在我们的情况下,我们想要确定这种过载是不是特别困难:

template<typename T>
void f(std::shared_ptr<T>);
Run Code Online (Sandbox Code Playgroud)

比这更专业:

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

虽然在这种情况下我们很容易根据我们的直觉来判断哪一个更专业,但编译器必须依赖于算法,并且该算法必须适用于所有情况.

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

  1. 取第一个重载,例如,将其template参数替换T为类型参数(任何类型参数)int,并实例化相应的签名 - 函数参数将具有类型std::shared_ptr<int>;
  2. 是否总是可以通过提供该类型的对象(在本例中)作为其输入来调用第二个重载shared_ptr<int>,并U从中推断出类型?
  3. 嗯,答案是肯定的.U将被推断为std::shared_ptr<int>;
  4. 现在是另一种方式:取第二个重载,例如,将其template参数替换U为任何类型参数bool,并实例化相应的签名 - 函数参数将具有类型bool;
  5. 是否始终可以通过提供该类型的对象()作为其参数来调用第一个重载boolT从中推导出类型?
  6. 当然,答案是否定的.没有办法推断,T以便std::shared_ptr<T>匹配bool;
  7. 结论:第一次过载比第二次过载更专业.

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