6 - 模板参数推导
本文是有关模板参数推导方面知识的补充,补充了有关实参依赖查找(ADL)、万能引用与引用折叠等知识点。
一个模板参数同时只能被推导为一个具体类型。
实参依赖查找(ADL)
实参依赖查找(ADL)是一组对函数调用表达式种无限定的函数名进行查找的规则,例如在使用自己编写的max()
比较两个string
对象时,可能调用的是std::max()
,而不是自己编写的max()
。如果要用自己编写的,可以这样写:::max()
。
万能引用与引用折叠
万能引用
也称作转发引用,即 如果接收到左值表达式,那么形参类型推导为左值引用;如果接收到右值表达式,形参类型推导为右值引用。
例如:
template<typename T>
void f(T&& t) {}
int a = 10;
f(a); // a是左值, 接收f<int&>后, T是int&
f(10); // 10是右值, 接收f<int>后, T是int&&
引用折叠
有时会碰见“引用的引用”这类套娃情况,此时适用 引用折叠(Reference collapsing) 规则,即 右值引用的右值引用折叠成右值引用,所有其他组合均折叠成左值引用。
例如:
// typedef/using中的类型操作(不常见)
using lref = int&;
using rref = int&&;
int n;
lref& r1 = n; // r1 的类型是 int&
lref&& r2 = n; // r2 的类型是 int&
rref& r3 = n; // r3 的类型是 int&
rref&& r4 = 1; // r4 的类型是 int&&
// 模板中的类型操作, 这里直接把 std::forward 定义拿过来了
template <class Ty>
constexpr Ty&& forward(Ty& Arg) noexcept {
return static_cast<Ty&&>(Arg);
}
int a = 10;
::forward<int>(a); // 返回 int&&, 因为 Ty 是 int,Ty&& 就是 int&&
::forward<int&>(a); // 返回 int&, 因为 Ty 是 int&,Ty&& 就是 int&
::forward<int&&>(a); // 返回 int&&, 因为 Ty 是 int&&,Ty&& 就是 int&&
参考资料
- 飘零的落花 - 现代C++详解
- Modern-Cpp-templates-tutorial/md/第一部分-基础知识/01函数模板.md at main · Mq-b/Modern-Cpp-templates-tutorial (github.com)
- C++20高级编程