C++ Primer 第16章 知识点回顾
来源:互联网 发布:java使用redis统计 编辑:程序博客网 时间:2024/06/05 03:47
16.1.1 函数模板
- 非类型模板参数:用户提供的值必须是常量表达式,从而允许编译器在编译时实例化模板
- 在模板定义内,模板非类型参数是一个常量值,在需要常量表达式的地方,可以使用非类型参数,例如指定数组的大小
- 模板程序应该尽量减少对实参类型的要求
- 函数模板与类模板成员函数的定义通常放在头文件中。而类成员函数和普通函数的定义通常放在源文件,同时类定义和函数声明放在头文件中
16.1.2 类模板
- 与函数模板不同,编译器不能为类模板推断模板参数类型,必须使用模板实参列表。
- 类模板的每个实例都有自己版本的成员函数
- 标准库函数
make_shared<T>(args);
- 默认情况下,一个类模板的成员函数只有当程序用到它时才进行实例化。默认情况下,对于一个实例化了的类模板,其成员只有在使用时才被实例化
template<typename> class Blob;//模板声明
静态成员类外定义和初始化:
template<typename T>
size_t Foo<T>::ctr=0;模板不是一个类型,模板实例化出的类才是类型
16.1.3 模板参数
- 与任何其他名字一样,模板参数会隐藏外层作用域中声明的相同名字。但是,与大多数其他上下文不同,在模板内不能重用模板参数名。由于参数名不能重用,所以一个模板参数名在一个特定模板参数列表中只能出现一次
当我们希望通知编译器一个名字表示类型时,必须使用关键字typename,而不是class**即,使用模板类型参数的类型成员时必须用typename**
template<typename T>
typename T::value_type top(const T&c)/*默认情况下,C++语言假定通过作用域运算符访问的名字不是类型,因此如果我们希望使用一个模板类型参数的类型成员,通过使用typename显示告诉编译器该名字是一个类型*/默认模板实参
Numbers<> average_precision;
16.1.4 成员模板
- 与类模板的普通函数成员不同,成员模板时函数模板,在类外定义成员模板时:
template<typename T>//类的类型参数
template<typename It>//构造函数的类型参数
Blob<T>::Blob(It b,It e) {...};
16.1.5控制实例化
- 显示实例化:
extern template class Blob<string>;//实例化声明
template int compare(const int&,const int&);//实例化定义(实例化类模板的所有成员)
16.2.1 类型转换与模板类型参数
- 将实参传递给带模板类型的函数形参时,能够自动应用的类型转换只有const转换及数组或函数到指针的转换
- 如果函数参数类型不是模板参数吗,则对实参进行正常的类型转换
16.2.2 函数模板显式实参
template<typename T1,typename T2, typename T3> T1 sum(T2,T3);
auto val3=sum<long long>(i,lng);//long long sum(int,long)- 如果我们显式指定了模板类型参数,就可以进行正常类型转换了
16.2.3 尾置返回类型与类型转换
- 由于尾置返回出现在参数列表之后,他可以使用函数的参数
template<typename It>
auto fcn(It beg, It end)->decltype(*beg)//得到引用类型,返回引用类型
{
//处理序列
return *beg;
}- 标准库类型转换模板:
remove_reference<decltype(*beg)>::type;
template<typename It>
auto fcn(It beg, It end)->typename remove_reference<decltype(*beg)>::type//使用模板类的类型成员必须使用typename
{
//处理序列
return *beg;
}
16.2.5 模板实参推断和引用
- 引用折叠只能引用于间接创建的引用的引用,如类型别名或模板参数
- 如果一个函数参数是指向模板参数类型的右值引用(如,T&&),则可以传递给他任意类型的实参。如果将一个左值传递给这样的参数,则函数参数被实例化为一个普通的左值引用(T&)(通过引用折叠)
16.2.6 理解 std::move
- 将一个左值static_cast到一个右值引用时允许的:虽然不能隐式地将一个左值转换为右值引用,但是我们可以用static_cast显式地将一个左值转换为一个右值引用
template<typename T>
typename remove_reference<T>::type && move(T &&t)
{
return static_cast<typename remove_reference<T>::type &&>(t);
}
16.2.7 转发
- 如果一个函数参数是指向模板类型参数的右值引用(如T&&),它对应的实参的const属性和左值右值属相将得到保持。
- **通常情况下,我们使用forward传递哪些定义为模板类型参数的右值引用的函数参数。**forward返回类型是T&&。通过返回类型上的引用折叠,forward可以保持给定实参的左值右值属性
- 当用于一个指向模板参数类型的右值引用函数参数(T&&)时,forward会保持实参类型的所有细节
16.4 可变参数模板
- 模板参数包,函数参数包
- 包扩展:分解为构成的元素,对每个元素应用模式
- 转发:
std::forward<Args>(args)...;
- 可变参数函数通常将他们的参数转发给其他函数
template<typename...Args>
void fun(Args&&...args)//将Args扩展为一个右值引用的列表
{
//work的实参既扩展Args又扩展args
work(std::forward<Args>(args)...);
}
16.5 模板特例化
- 一个特例化版本就是模板的一个独立的定义,在其中一个或多个模板参数被指定为特定的类型
- 特例化的本质是实例化一个模板,而非重载他。因此,特例化不影响函数匹配
- 模板及其特例化版本应该声明在同一个头文件中,所有同名模板的声明应该放在前面,然后是这些模板的特例化版本
- 全特例化、偏特化(部分特例化)(只有类模板特例化才可以偏特化,函数模板必须全特例化)
- 可以特例化类的一个成员函数
0 0
- C++ Primer 第16章 知识点回顾
- C++ Primer 第2章 知识点回顾
- C++ Primer 第3章 知识点回顾
- C++ Primer 第4章 知识点回顾
- C++ Primer 第5章 知识点回顾
- C++ Primer 第6章 知识点回顾
- C++ Primer 第7章 知识点回顾
- C++ Primer 第8章 知识点回顾
- C++ Primer 第9章 知识点回顾
- C++ Primer 第10章 知识点回顾
- C++ Primer 第11章 知识点回顾
- C++ Primer 第12章 知识点回顾
- C++ Primer 第13章 知识点回顾
- C++ Primer 第14章 知识点回顾
- C++ Primer 第15章 知识点回顾
- C++ Primer 第17章 知识点回顾
- C++ Primer 第18章 知识点回顾
- C++ Primer 第19章 知识点回顾
- 上升子序列
- hahaha
- 【嵌入式学习日记】2016年8月12日
- 那些值得你试试的Android竞品分析工具
- Big Number
- C++ Primer 第16章 知识点回顾
- Javascript
- Android颜色对照表
- Android studio快捷键大全 和 eclipse对照(原)
- hdu5325 Crazy Bobo(建图,搜索)
- 项目实战--PC端固定布局[4]之figure
- 数组与指针的操作
- Android线程池源码解析
- html图片上传阅览并且点击放大