条款1(理解模板类型推导)
模板和调用的一般形式:
template
void f(ParamType param);
f(expr);
从expr来推导T 和ParamType的类型
情况1:ParamType是个指针或引用,但不是个万能引用 推导:
1.若expr具有引用类型,先将引用部分忽略
2.对expr的类型与ParamType的类型进行模式匹配,来决定T的类型
3.左值引用和右值引用相同
左值引用模式如下:
template
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&
const左值引用模式如下:
template
void f(const T& param); //param是个引用
声明变量:
int x = 27;
const int cx = x;
const int &rx = x;
调用与推导:
f(x); // T的类型是 int,param的类型是const int&
f(cx); // T的类型是 int,param的类型是const int&
f(rx); // T的类型是 int,param的类型是const int&
【条款1(理解模板类型推导)】指针模式如下:情况2:ParamType是个万能引用 推导:
template
void f(T* param); //param是个引用
声明变量:
int x = 27;
const int* px = &x;
调用与推导:
f(&x); // T的类型是 int,param的类型是 int*
f(px); // T的类型是 const int,param的类型是const int*
1.若expr是个左值,T和ParamType都会被推导为左值引用
2.如果expr是个右值,则引用常规的规则
template情况3:ParamType既非指针也非引用 当ParamType既非指针也非引用时,我就是所谓的按值传递了:
void f(T&& param); //param是个万能引用
声明变量:
int x = 27;
const int cx = x;
const int& rx = x;
调用与推导:
f(x); // x是个左值,所以T的类型是 int&,param的类型是 int&
f(cx); // cx是个左值,所以T的类型是 const int&,param的类型是const int&
f(rx); // rx是个左值,所以T的类型是const int&, param的类型是const int&
f(27); //27是个右值,所以T的类型是个int,param的类型是int&&
推导:
1.若expr具有引用类型是,忽略其引用部分
2.忽略引用性后,若expr是const对象或者volatile对象,也忽略
templateparam是个完全独立于cx和rx存在的对象----是个cx和rx的一个副本。expr不可修改,并不能断定其副本也不可修改。
void f(T param); //param按值传递
声明变量:
int x = 27;
const int cx = x;
const int& rx = x;
调用与推导:
f(x); // T和param都是int
f(cx); // T和param都是int
f(rx); // T和param都是int
情况4:expr是个涉及到const对象的const指针,并且expr按值传给你param
template情况5:数组实参 数组类型有别于指针类型,虽然有时他们看起来可以互换。形成这种假象的主要原因就是,在很多语境下,数组会退化成指涉到其首元素的指针。
void f(T param); //param 按值传递
const char* const ptr = "fun with pointers"; //ptr是个涉及到const对象的const指针
f(ptr); //传递类型为const char* const的实参
位于星号右侧的const将ptr声明为const:ptr不可以指涉到其他内存位置,也不可以被置为null[位于星号左侧的const则将ptr指涉到的对象(那个字符串)为const,即字符串不可修改]。ptr会按值传递,ptr的常量性会被忽略,param的类型会被推导成const char*,即一个可修改的,指涉到一个const字符串的指针。在推导过程中,ptr指涉到的对象的常量性会被得到保留,但其自身的常量性会在以复制的方式创建新指针param的过程中被忽略。
const char name[] = "j. p. briggs"; //name的类型为const char[13]
const char * ptrToName = name; //数组退化成指针
template
void f(T param);
f(name)
name是个数组,但是T的类型却会被推导为const char*
尽管函数无法声明为真正的数组类型的形参,但是它们却能够将形参声明成数组的引用利用声明数组的引用的能力创造一个模板,用来推导出数组的含有的元素个数:
template
void f(T& param);
f(name)
T得类型会被推导为const char [13],param的类型会被推导为const char (&)[13]
template
constexpr std::size_t arraySize(T (&)[N]) noexcept
{
return N;
}
int keyVals[] = {1,2,4,78,5,5,7};
std::array mappedVals;
情况5:数组实参 数组并非c++中唯一可以退化为指针之物。函数类型也同样会退化成函数指针,并且数组的类型推导适用于函数及其向函数指针的退化。
void someFunc(int, double); // someFunc是个函数,其类型为void(int, double)
template
void f1(T param); // 按值传递
template
void f2(T& param); // 按引用传递
f1(someFunc); //param 被推导为函数指针,具体类型为void (*)(int, double)
f2(someFunc); //param 被推导为函数引用, 具体类型为void (&)(int, double)
推荐阅读
- 深入理解Go之generate
- 考研英语阅读终极解决方案——阅读理解如何巧拿高分
- 由浅入深理解AOP
- 逻辑回归的理解与python示例
- opencv|opencv C++模板匹配的简单实现
- 「按键精灵安卓版」关于全分辨率脚本的一些理解(非游戏app)
- 深入理解|深入理解 Android 9.0 Crash 机制(二)
- 不理解句意,你还想做对所有GRE填空题()
- web网页模板|如此优秀的JS轮播图,写完老师都沉默了
- 如何理解“超我、自我、本我”