在编译器中打印_cplusplus 查看编译器是否已经支持c++ 2.0
Alias Template 化名
template <typename T>
//Vec<int> 就是std:: vector<int,MyAlloc<int>>
using Vec = std::vector<T,MyAlloc<T>>;
#define 与tepedef都无法做到一样的效果 #define会把 template 的T也变成具体的类型,typedef不能接受参数
举例子
需求: 一个测试函数,希望函数的两个参数是一个容器种类,一个元素类型
函数的传参必须是一个Object(对象),因此不行,换个思路:
list() 是一个临时对象,通过传入一个临时对象获取到对象类型,进行测试,但是编译器不知道Container是一个模板,编译器会假设Container为一个变量名,再试试,我们在前面加上typename 告诉编译器Container是一个type(类型)而非变量名
编译器期待typename后有个 ::
继续换思路
另向思考在标准库中是不存在的,容器当然有迭代器
有没有能在模板接受一个参数,而那个参数本身也是个模板,从中取出元素类型,比如传一个vector 取出string
template template paramete 模板模板参数
函数有第二参数 ,因此使用alias template ,加上alias template
Type Alias 类型化名
类似于typedef
如下两行效果是一样的
typedef void (*fun)(int,int);
using func=void(*)(int,int);
noexcept
在函数声明或者定义后面加上 noexcept或者noexcept(true) 说明此函数不会抛出异常,注意()中可以是表达式
在定义类的移动拷贝构造的时候,加上noexcept,在此类的容器需要成长的编译器才会用此函数
override final
在子类重载override父类的函数的时候,在后面加上override,编译器会查错
在定义类的时候类名后面加上final,表示这个类不可以被继承
在类中某个虚函数后面加上final,。表示此函数不可以被重载override
decltype
当想知道一个表达式的类型时
- 用法一
map<string,float> coll;
...
decltype(coll)::value_type elem;//获取到coll的类型,通过对象来获取到类型
template<typename T1,typename T2>
//dectype(x+y) add(T1 x,T2 y);//允许我们通过x+y定义add的返回值类型,注意x,y是两个类型,但是先出现的x+y,编译器不知道x,y是啥,因此写下面这行
auto add(T1 x,T2 y)->dectype(x+y);
-
用法二
在模板函数中用于类型推到 -
用法三
获取lambda的类型
lambda
lambda是一个小东西,像一个内联函数,但实质是一个对象
//最简单的形式
auto l=[]{
cout<<"hello lambda"<<endl;
};
...
l()//调用这个lambda
完整形式:
[…] (…) mutable throwSpec -> retType {…}
- 三个关键字都是可选的,如果都不写,小括号也可以省略,只要有一个写了,小括号就得有
- ()放函数的参数
- 外部的变量
- mutable 参数是否可以改
- throwSpec 异常
- retType 返回值类型
左边的lambda就等同于右边(左边加了mutable,参数可以改变,如果不加就不能改变),程序自上而下执行,id是值传递,因此执行f()时,出现的是从0开始,lambda像一个匿名函数对象或者仿函数
从左至右,传值可变, 传引用,传值不可变(因此编译报错),
lambda会相当于2处的代码
创建一个无序容器的时候,尖括号中第一个参数是数据类型,第二个参数是比较的方法,传入一个类型,通过decltype获取到lambda的类型传入,并通过调用右边的构造函数,构造一个set,如果在初始化不写第二个cmp,那就会调用右边倒数第二行的构造函数,调用Compare的默认构造,但是lambda没有默认构造函数,因此会报错。
Variadic Templates
参考11/14笔记(1)开头,
使用Variadic Templates重写c的printf
- 想要处理一堆数据,但是头和尾处理方式不同,可以采用如下方式,递归的创建模板类
- make_tuple将后面的东西组合成一个整体
- 用于递归的继承
- 第一个元素创建了类的头元素,其他的一大包变成父节点类,调用tail得到除了头元素的其他第一个元素创建了类的头元素,其他的一大包变成父节点类
typename那块有错误,Head是一个typename,不能获取到type,改写成下面的样子,其实小题大做了直接用Head就可以了
Head head(){ return m_head}
- 用于递归复合,目的都是为了把不同的数据类型的数据组合成一个数据