|
|
7 月之前 | |
|---|---|---|
| .. | ||
| C++模板_第二版.pdf | 7 月之前 | |
| README.md | 7 月之前 | |
类型推断中的类型转换
在类型推断的时候自动的类型转换是受限制的:
const 和 volatile 限制符会被忽略,引用被转换成被引用的类型,raw array 和 函数 被转换为相应的指针类型。通过模板类型参数T定义的两个参数,它们实参的类型在退化( decay )后必须一样template<typename T>
T m_max(T& a, T& b)
{
return a > b ? a : b;
}
template<typename T>
T mmmax(T a, T b)
{
return a > b ? a : b;
}
int const c = 42;
int i = 1;
int& ri = i;
mmmax(c, c); // ok
mmmax(c, i); // ok
mmmax(ri, c); // ok
m_max(c, c); // ok
m_max(c, i); // error 如果模板函数参数是 T& 引用,则任何转换都不允许
m_max(ri, c); // error 同理 由于参数是 T& 无法转化
默认调用参数的类型推断
类型推断并不适用于默认调用参数,比如下面的 foo_1 函数,虽然设置了 x 的默认值是 "12",但是编译器并不会认为 x 的默认类型是 std::string, 需要像 foo_1_o 中设置 T = std::string,编译器才知道 T 的默认类型是 std::string
template<typename T>
void foo_1(T x = "12")
{
std::cout << "x = " << x << std::endl;
}
template<typename T = std::string>
void foo_1_o(T x = "123")
{
std::cout << "x = " << x << std::endl;
}
foo_1(1); // 正确的
// foo_1(); // 错误的 因为未明确参数类型 无法给形参 x 定义
foo_1<std::string>(); // 正确的
// foo_1<int>(); // 错误的 定义形参 x 为 int 无法使用默认值 "123"
foo_1_o(); // 正确的 指定 T 的默认类型为 std::string
多个模板参数
如果想要让函数接受传入两个不同类型的参数,可以通过 typename 定义多个类型
template<typename T1, typename T2>
T1 mTest(T1 a, T2 b)
{
std::cout << typeid(a).name() << " " << typeid(b).name() << std::endl;
return a < b ? a : b;
}
int main() {
std::cout << mTest(2, 1.1) << std::endl;
return 0;
}
不过有一个问题,那就是 mTest 函数的返回值类型是 T1,以 mTest(2, 1.1) 来说返回值类型是 int, 但是返回的值却是 1.1 导致数据类型转换,最终得到的是 1
为了解决这个问题
引入第三个模板参数的解决方法如下
// 解决方法 1
template<typename RT, typename T1, typename T2>
RT mTest(T1 a, T2 b)
{
std::cout << typeid(a).name() << " " << typeid(b).name() << std::endl;
return a < b ? a : b;
}
// mTest<int, double, double>(2, 1.1);
// mTest<double>(2, 1.1); // T1 和 T2 的类型能够通过编译器推理出来,只用显式指定 RT 类型为 double 即可
让编译器找出返回类型的解决方法如下,使用 C++ 提供的类型推导 decltype
| 组成部分 | 作用 | |
|---|---|---|
| b < a | 类型检查:确保这两个类型可以比较 | 必要 |
| ? a : b | 类型推导:确定条件表达式的公共类型 | 核心 |
无论 mTest(1, 1.1) 还是 mTest(2, 1.1) 返回类型都是 double, 因为通过 ? a : b 类型推导得到公共类型是 double,与传入参数的 a,b 的具体值没有关系
// 解决方法 2
template<typename T1, typename T2>
auto mTest (T1 a, T2 b)-> decltype(b<a?a:b)
{
return b < a ? a : b;
}
不要以为
mTest(1, 1.1)返回值类型是int
如果传入参数是 int 和 std::string, 就算类型比较能够通过,但是 int 和 std::string 是没有公共类型的 decltype 会在编译器报错