effective modern c++
函数模板可以看成是这样:
template<typename T>
void f(ParamType param);
ParamType param = expr
分三种情况:
三种情况的推导规则:(推导规则推导的是T的类型)
1
ParamType是一个指针或者引用(非通用universal reference引用)
2
ParamType是一个通用引用(universal reference)
3
ParamType既不是指针也不是引用
实际测试:
template<typename T>
void f(T& param); // param是一个引用类型
int x = 27;
const int cx = x;
const int& rx = x;
f(x); //T: int param: int &
f(cx); //T: const int param: const int &
f(rx); //T: const int param: const int &
template<typename T>
void f(T&& param);
int x = 27;
const int cx = x;
const int& rx = x;
f(x); //T: int & param: int &
f(cx); //T: const int & param: const int &
f(rx); //T: const int & param: const int &
f(27); //T: int&& param: int &&
A&& --> A&
A&&& --> A&
A&&& --> A&
A&& && --> A&&
case2的param经过了引用折叠:
int & && --> int &
const int & && --> const int &
const int & && --> const int &
int && && --> int &&
template<typename T>
void f(T param);
int x = 27;
const int cx = x;
const int& rx = x;
f(x); //T: int param:int
f(cx); //T: int param:int
f(rx); //T: int param:int
数组会退化为指针:
const char name[] = "J. P. Briggs"; // name的类型是const char[13]
const char * ptrToName = name; //数组退化成指针
template<typename T>
void f(T param);
f(name); //T: const char*
数组的引用会保留为数组形式:
const char name[] = "J. P. Briggs"; // name的类型是const char[13]
template<typename T>
void f(T ¶m);
f(name); //T: const char[13] param: const char (&)[13]
函数类型退化成函数指针:
void someFunc(int, double); //void (int, double)
template<typename T>
void f1(T param);
f1(someFunc); //T: void (*)(int, double)
函数引用会保留为函数形式:
void someFunc(int, double); //void (int, double)
template<typename T>
void f2(T& param);
f2(someFunc); //T: void (&)(int, double)
auto类型推导和模板类型推导基本一致,auto相当于T,只有一个例外:{}
auto x1 = 27; //auto: int
auto x2(27); //auto: int
auto x3 = {27}; //auto: std::initializer_list<int>
auto x4{ 27 }; //auto: std::initializer_list<int>
auto x5 = { 1, 2, 3.0 }; //编译失败,类型不一致
decltype可以表示变量或者表达式的类型
使用方式:
decltype(expr) a;
注意点:
对一个变量名使用 decltype 得到这个变量名的声明类型。变量名属于左值表达式,但这并不 影响 decltype 的行为。然而,对于一个比变量名更复杂的左值表达式, decltype 保证返回 的类型是左值引用
int x = 0;
decltype(x) a; //a: int
decltype((x)) a; //a: int &
//c++11版本
//auto作为函数返回值,不能推导出c和i的类型,因为这时候c和i还没有声明
//通过--> decltype(c[i])表示函数返回值类型在函数参数后声明
template<typename Container, typename Index>
auto authAndAccess(Container& c, Index i)
-> decltype(c[i])
{
authenticateUser();
return c[i];
}
//c++14版本
//c++14这样是可以编译过的,但是auto进行了类型推导并不和c[i]类型一致
template<typename Container, typename Index>
auto authAndAccess(Container &c, Index i)
{
authenticateUser();
return c[i];
}
//c++14版本
//返回值类型和c[i]保持一致
template<typename Container, typename Index>
decltype(auto) authAndAccess(Container &c, Index i)
{
authenticateUser();
return c[i];
}
//使用完美转发更好,以后总结完美转发
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。