1.2 模板参数推导

Posted rileyye

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1.2 模板参数推导相关的知识,希望对你有一定的参考价值。

  当我们传入参数调用函数模板时,比如调用 max(),模板参数就被我们传进去的参数类型所决定。如果我们传进去两个 int , C++ 编译器就能推导出  T 是 int 类型的。

  然而,T 有可能只是类型的一部分。比如,如果我们把 max() 定义成参数为常引用的函数:

  

template <typename T>
T max(const T& a, const T& b)
{
    return b < a ? a : b;
}

  如果这时候我们传进 int ,T 也会被推导成 int,因为函数参数和 const int& 匹配。

  类型推导期间的类型转化

  请注意,在类型推导期间,自动类型转换被限制。

  1.   当参数是引用类型时,即使是简单的类型转换也不会被推导。模板参数 T 声明的两个参数必须完全匹配。
  2.        当参数是值类型时,只支持退化的转换。这时候 const 和 volatile 限定被忽略,而 C 风格数组和函数会退化成相应的指针。 对于用相同模板参数 T 声明的两个参数,退化成的类型必须匹配。

  例如:

  

template <typename T>
T max(T a, T b);
...
int i = 17;
const int c = 42;
max(i ,c);  // 正确 : T 被推导成了 int
max(c, c);  // 正确 : T 被推导成了 int
int& ir = i;
max(i, ir);  // 正确 : T 被推导成了 int
int arr[4];
max(&i, arr); // 正确 : T 被推导成了 int*

  然而,下面这些是错误的。

max(4, 7.2);  // 错误: T 能被推导成 int 或者 double
std::string s;
max("hello", s);  // 错误:T 能被推导成 const char[6] 或 std::string

  有三种方式能解决此类错误:

  1. 对参数进行类型转换,让所有参数的类型都与模板匹配。

max( static_cast<double>(4), 7.2); // 正确

  2. 指定 T 的类型,以此来防止编译器进行类型推导。

max<double>(4, 7.2); // 正确

  3. 给类型可能不同的参数指定不同的模板参数。1.3 节会对此详细说明。 15 章 第7.2 节会详细讨论在类型推导时,类型转换的规则。

 

  默认参数的类型推导

  请注意,类型推导并不对默认参数起作用。比如:
  

template <typename T>
void f(T = "");
f(1);  // 正确:T 被推导成 int,因此它调用的是 f<int>(1)
f();  // 错误:不能推导 T

  为了解决此问题,你得为模板参数声明一个默认类型。这在 1.4 节里会讨论到。

template<typename T = std::string>
void f(T = "");
...
f();  // 正确

 

以上是关于1.2 模板参数推导的主要内容,如果未能解决你的问题,请参考以下文章

模板参数推导失败

参数和返回类型中的模板类型推导

C++ 模板参数推导/替换失败:

带有函数指针和引用的模板参数推导[重复]

用右值/左值理解模板参数推导

C++ 中聚合的带括号初始化的模板参数推导