以下列代码为例子,当调用func(expr)
时,编译器会自动推导出来T
的类型和ParamType
的类型,模板类型推导分为一下三种类型:
template<typename T> void func(ParamType p);
- 当ParamType是指针或者引用类型,并且不是通用引用类型 ,如果
expr
的类型是引用类型,丢掉其引用类型。然后用expr
的类型去匹配ParamType
以确定T
的真实类型,例如:
template<typename T> void func(T& p); int x = 0; const int cx = x; const int& rx = x; f(x); //ParamType 为 int&, T 为 int f(cx); //ParamType 为 const int&, T 为 const int f(rx); //ParamType 为 const int&, T 为 const int
ParamType
是通用引用类型,如果expr是一个lvalue,T会被推断为对应expr裸类型的左值引用,而根据引用折叠规则,ParamType也被推断为左值引用,如果expr是一个rvalue,情况1生效,即expr会被推断为对应的裸类型,而ParamType将会是裸类型对应的右值引用类型,例如:
引用折叠规则:
- 到右值引用的右值引用折叠成右值引用
- 其他所有情况折叠左值引用
template<typename T> void func(T&& p); int x = 0; const int cx = x; const int& rx = x; f(x); //x 为左值,ParamType 为 int&,T 为 int& f(cx); //cx 为左值,ParamType 为 const int&,T 为 const int& f(rx); //rx 为左值,ParamType 为 const int&,T 为 const int& f(0); //0 为右值,ParamType 为 int&&, T 为 int
- ParamType既不是指针也不是引用,如果expr的类型中含有引用,const,volatile,则舍弃这些,然后用expr的裸类型去匹配T