成员模板就是在一个类里面再声明一个模板,一般来说这个模板是为了能够在类里面实现利用派生类对其进行一个初始化。为了设计一个构造函数,以pair为例子。
利用派生类鲫鱼和麻雀,来构造父类的对象,鱼类和鸟类。这就是成员模板在标准库里的用途。
模板的特化:
template <class Key>
struct hash{};//泛化
template<>//特化
struct hash<char>{
size_t operator() (char x) const { return x;}
};
template<>
struct hash<int>{
size_t operator() (int x) const { return x;}
};
template<>
struct hash<long>{
size_t operator() (long x) const { return x;}
};
如果我们指定了任意的类型,都会去泛化里面,如果这个类型是char,int,long被我们特化过的,就选择特化的版本。
如 cout << hash<long>()(1000)<< endl; hash<long>()表示一个临时对象。
模板的偏特化:partial specialization
1、个数上的偏
template<typename T,typename ALLoc=...>
class vector{
};
template<typename ALLoc=...>
class vector<bool,ALLoc>//偏特化,T被绑定为了bool,ALLOC还未定,但是这里要写出来了
{
};
多个参数也是一样,但是不能跳着绑定参数,不能是1,3,5
2、范围上的偏
template <typename T>
class C{
...
};
template <typename T>
class C<T*>{
...
};
指针的范围比typename要小,所以进行了一部分特化,如果说传入的是普通类型就进行泛化版本,如果是指针类型,就进行下面的版本。
C<string> obj1;
C<string*> obj2;
模板模板参数,在模板里面再加入一个模板作为其参数。
在模板里面的参数早先为class,后来出现了typename所以在模板参数里面typename和class共通。
template<typename T,
template<typename T>
class Container
>
class XCls
{
private:
Container<T> c;
public:
...
};
template<typename T>
using Lst = list<T,allocator<T>>;//必须加上才能用
XCls<string,list> mylst1;//x错误,虽然我们平时写list只会含一个参数,但其实容器是含有第二个模板参数的,有的还有第三个
XCls<string,Lst> mylst2;
现在改正一下,传入的参数使用一个模板参数的对象。template<typename T,
template<typename T>
class Smart_ptr
>
class XCls
{
private:
Smart_ptr<T> c;
public:
XCls():sp(new T);
};
XCls<string,shared_ptr> p1;//对
XCls<double,unique_ptr> p1;//错
XCls<int,weak_ptr> p3;//错是因为其独特的特性
XCls<long,auto_ptr> p4;//对
和之前的写法不太一样,这里不是模板模板参数,如果写出的话,必须写出其实例了,没有模糊替代了,list<int>已经写死了。之前一个是模糊的,所以才是一个模板