各类关键字
测试程序使用namespace包裹
示例代码:
类模板
可以允许使用者任意指定的部分可以抽出成为模板
template<typename T>
// 使用的时候在指明类型
class complex
{
public:
complex (T r = 0. T i = 0) : re(r), im(i) {}
complex& operator += (const complex&);
T real() const {return re;}
T imag() const {return im;}
private:
T re, im;s
}
函数模板
语法和类模板一样
template<typename T>
inline
const T& min(const T& a, const T& b) {return b < a ? b : a;}
// 使用的时候不需要指名类型 -> <符号的本质是操作符重载
stone r1(2, 3), r2(3, 3);
r3 = min(r1, r2);
成员模板
模板里面的member,该member本身又是一个template -> 模板内的模板 -> 主要用来设计构造函数
示例代码:
template<class T1, class T2>
struct pair
{
T1 first;
T2 second;
pair() : first(T1()), second(T2()) {}
pair(const T1& a, const T2& b) : first(a), second(b) {}
// 再设计模板
template<class U1, class U2>
pair(const pair<U1, U2>& p) : first(p.first), second(p.second) { }
};
模板特化
专门针对某一类型设计的函数
示例代码:
partial specialization 模板偏特化(个数的偏特化,范围的偏特化)
个数偏特化:
template<typename T, typename Alloc=...>
class vector
{
}
T是指定函数类型.Alloc是指定函数的分配器(标准库的内容)
c++当中最小单位是char类型.八位,如果是bool类型那么只占用一位.那么就不需要使用泛化
实际上就是在声明模板的时候指定一个模板的泛化值是什么(类似声明形参的时候赋予初始值)
示例代码:
template<typename Alloc=...>
class vertor<bool, Alloc>
{
}
范围上的偏特化
如果设计一个模板特化类型T,但是他不是一个具体的类型.他是一个指针.指向任意类型.所以T的范围就缩小了
示例代码:
template<typename T>
class C
{
}
在声明一个指针的T
template<typename U>
class C<U*>
{
}
如果使用者用的是指针,编译器会使用下面一套代码.如果是指针,那么编译器会用上面一套代码
T*表示指向什么都可以
使用者声明方式:
c<string> obj1; // 使用上面一个T代码
c<string*> obj2; // 使用下面一个U*代码
template template parameter模板模板参数
声明一个模板.有两个参数.第二个参数也是一个模板
示例代码:
目的是为了让使用者可以指定使用容器来构造类
容器需要指定元素类型和分配器
上面的模板模板声明完成后具体使用:
// 错误使用方式
// XCls<string, list> mylst1; -> list传入就是第二个Contrainer,会拿前面的T当前元素类型
// 之所以这里可以这样使用,是因为元素有第二模板参数.只是有默认值.如果这样使用语法过不了
// list的特性接收两个参数
XCls<string, Lst> mylst;
上诉代码当中传入的list并没有绑定任何参数,所以它仍然是一个模糊的东西.这样才可以把它称之为模板
无法通过的原因是:容器接收好几个参数
如果只接收一个参数那么是可以通过的
示例代码:
使用方式:
XCls<string, shared_ptr> p1;
// XCls<double, unique_ptr> p2; -> 由于unique_ptr的特性所以上述的声明方式进行这样构造是不可以的
非模板模板偏特化:
template<class T, class Sequence = deque<T>>
class stack {
friend bool operator== <> (const stack&, const stack&);
friend bool operator< <> (const stack&, const stack&);
protected:
Sequence c; // 底层容器
};
在这段代码当中,由于Sequence有默认初始值.所以在声明调用的时候有两种方式:
stack<int> s1;
stack<int, list<int>> s2;
在这个当中如果要修改第二个初始值.需要指定list<int>并且向list当中传入参数.那么它就不是一个模糊的值.而是一个被定义的值.所以不能视为模板
小结
It's a lonely road!!!

浙公网安备 33010602011771号