template详解
来源:互联网 发布:知柏地黄丸吃多久为好 编辑:程序博客网 时间:2024/04/30 10:14
1. 函数模板
1. 函数模板定义
关键字:“template开头”,“参数列表非空”
定义一定要以:template<…>开头(为了解释为什么 inline 在第 2 位置)
定义中模板参数列表不能为空(模板特例化中参数列表可以为空)。
template<tempname T> inline T funcName(const T &a, const T &b) { return (a + b); } //inlinetemplate<tempname T> T funcName(const T &a, const T &b) { return (a + b); }template< > void funcName() { } //错误:定义时模板参数不能为空。
2. 函数参数
关键字:“非类形形参为常数”,“泛型编程规则”,“const引用”
在下面的代码中,其中T为类型形参,类型在编译器进行实例化(instantiate)时确定,T还可以用来做类型转换。v为非类型形参,v的实例必须为常数。
template<class T, T v> void foo(T &a, T &b){ b = v; cout<<"a = "<<a<<ends<<"b = "<<b<<endl; a = b;}int main(){ int m = 1; int n = 2; foo<int, m>(m, n); //error C2971: “foo”: 模板参数“v”:“m”: 局部变量**不能用作非类型参数** cout<<"a = "<<m<<ends<<"b = "<<n<<endl; return 0;}
泛型编程中,函数的参数常常为const引用,来保证参数不仅可为拷贝类型,也可以是非拷贝类型,并且能够保证对源数据的只读性。函数内部的判断符号使用 <,目的是减小函数对要处理类型的要求,因为有的类型肯可能并没有对其他运算符进行重载。
3. 实例化
实例化目前我所了解的有两种:
编译器通过传入的实参进行推断类型形参的类型(即模板实参推断:template argument deduction/*推理*/),但是无法为非类形形参进行推断。
在调用函数时进行指定类型形参与非类形形参的类型。
template<class T, T v> void foo(T &a, T &b) { ... }foo(m, 5); //error C2783: “void foo(T &,T &)”: 未能为“v”推导 模板 参数/*正确的实例化*/template<class T, class V> void foo(T &a, V &b) { ... }foo(5, 5); //推断template<class T, T v> void foo(T &a, T &b) { ... }foo<int, 6>(5, 5); //指定
2. 类模板
1. 定义与实例化
大致与函数模板的定义相同。
template<class T> class Bob{public: void func(T &, T &); template<class It> void foo();private: T data;};
实例化一般在创建对象时指定类型,也可以进行类的特例化。
Bob<int> b; //实例化
2. 类模板的成员函数
关键字:“隐式内联”,“部分实例化”,“成员模板”
定义在类作用域内的成员函数隐式的被定义为内联函数。
成员函数在外部定义时,开头必须以 template<..> 开头。
template<class T> void Bob<T>::func(T &a, T &b){ data = a + b;}
成员模板函数不能是虚函数。
在类的外部,只有当遇到类名以后,才算该类的作用域。因此
Bob<T>
以后均为 Bob类的作用域,类的作用域中可以将 template
3. 编译模板
关键字:“定义在头文件”,“部分实例化”
当编译器遇到一个模板定义的时候,它并不生成代码。只有当我们实例化出模板一个特定的版本但是时候(即特例化时),编译器才会生成代码。或者在我们使用模板时,编译器才生成代码。
模板函数和模板类的成员函数通常在头文件中定义。
编译模板的三个过程:编译模板本身,编译器遇到使用模板,模板实例化。
错误一般在第三个阶段,模板实例化中检测到。模板实例化中是部分实例化,并非全部。仅仅实例化用到的模板。
4. 默认模板参数
默认模板参数时,跟函数默认实参一样,对于一个模板参数,只有当它右侧的所有参数都有默认实参时,它才可以具备默认实参。
template<class A = int, class B> A foo2() { ... } //error C4519: 仅允许在类模板上使用默认模板参数
默认值在使用模板的时候均可以修改(c++11新标准)
template<class A = int, int b = 0> int foo3() { return b; }int result = foo3<int, 7>(); //result = 7, okint result = foo3<double, 7>(); //result = 7, ok
5. 特例化模板(template specialization)
当面对特定的类型,模板不合适的时候,我们可以为这种类型量身打造一款特例化版本。
//定义template <bool b, typename B, typename C> class { ...};//部分特例化template <> class<true, int, int> { ...};//特例化template <typename B, typename C> class<false, B, C> { ...};
未了解的关于C++模板的知识
学无止境,还有很多未了解的C++模板知识和C++模板的使用(比如traits..),部分列举如下:
控制实例化:在大系统中,多个文件中实例化相同的模板,开销严重。使用显示实例化(explicit/*明确的*/ instantitation)来避免开销。
extern template class Bob; //声明:告诉编译器,在程序的其他位置(或者其他文件中)有string的实例化定义
tempalte int compare (const int&, const int&); //定义在运行是绑定删除器,在编译时绑定删除器(与智能指针有关)。
模板的参数推断。
理解std:move
转发:有的时候需要将一个或者多个实参连同类型转发给其他函数。
可变参数的模板
sizeof… 运算符
可变参数模板的编写
包扩展
转发参数包
struct和template连用实现traits
struct里面定义了类型和静态常数,需要用结构体名打点调用:
structName::defType i = value;template<class T, T v>struct integral_constant { static const T value = v; typedef T value_type; typedef struct integral_constant<T, v> type;};int i = struct integral_constant::value;
- template详解
- template详解
- Jdbc Template详解
- Jdbc Template详解
- Spring Jdbc Template详解
- Django Template 渲染机制详解
- template
- Template
- template
- template
- template
- Template
- template
- template
- Template
- template
- Template
- template
- hdu1010 扩展KMP求字符串最小循环节
- 获取和推送镜像
- android:screenOrientation属性
- Object-c------NSSet的简单介绍
- 如何查看手机里的.db数据库文件
- template详解
- el表达式及jstl标签库
- Qt静态库下载与安装说明
- windos系统下通过优盘安装Ubuntu14.04系统
- Android实现信息安全中凯撒密码技术
- 静态储存
- swift-struct
- ASP.NET基于角色的窗体安全认证机制
- ShellBash简单入门