plutolove’s diary

I love three things in this world, the sun, the moon and you. The sun for the day, the moon for the night, and you forever。

C++ 模板类型推导

以下列代码为例子,当调用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