自己写的程序最好用namespace包起来,不要直接使用全局的using namespace,尤其是代码量比较多的大程序。
成员模板
类模板在使用的时候,后面要加上模板参数,类型。
函数模板不需要加上模板参数,因为有参数,编译器会做实参推导。
成员模板
模板中的模板,往往在构造函数中使用的多,为了使构造函数更有弹性。在模板中包含了一个模板定义。
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.fisrt), second(p.second) {}
};
//使用:
class Base1 { };
class Derived1:public Base1 { };
class Base2 { };
calss Derived2:public Base2 { };
pair<Derived1, Derived2> p;
pair<Base1, Base2> p2(p);
pair<Base1, Base2> p2(pair<Derived1, Derived2>());
这里p2中的Derived1和Derived2到模板里面就是U1和U2。U1和U2必须是T1和T2的子类,能够使用first(p.fisrt), second(p.second) 进行初值设置。所以要通过集成来组织。
小类到大类的指针转换,就是up-cast。
template<typename _Tp>
class shared_ptr:public __shared_ptr<__Tp>
{
...
template<typename __Tp1>
explicit shared_ptr(__Tp1* __p)
: __shared_ptr<__Tp>(__p) { }
...
};
Base1* ptr=new Derived1;
shared_ptr<Base1> sptr(new Derived1);
up-cast相当于指针上移,变成父类指针。由于普通的指针包含这种up-cast的功能,智能指针也就要实现这种功能,所以在上面的shared_ptr中就看到了成员模板。
模板特化
就是把模板的局部具体化,特化。
//泛化:
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; }
};
上面的Key被绑定了,如果使用的时候,编译器会优先使用特化的。特化版本的多少不限制,可以有任意个。
偏特化
有两种:个数上偏、返回上的偏
个数上的偏:
如果模板的参数有多个,只绑定其中的个别。绑定必须从左到右,不能跳着绑定。
范围上的偏:
就是将模板参数的类型范围缩小。
template <typename T>
class C { ... };
//偏特化:
template <typename T>
class C<T*> { ... };
C<string> obj1;
C<string*> obj2;
obj2使用的偏特化,泛化的时候可以使用任意类型,偏特化之后只能使用指针。
模版模板参数
模板的参数也是一个模板:
template<typename T,
template <typenmae T>
class Container >
class XCls
{
private:
Container<T> c;
public:
...
};
template<typename T>
using Lst = list<T, allocator<T>>;
XCls<string, list> mylist1; //写法错误
XCls<string, Lst> mylist2;
上面的使用就是,想创建一个XCls的对象,里面能作出一个链表,链表的数据类型是string。
template<typename T,
template <typenmae T>
class SmartPtr
>
class XCls
{
private:
SmartPtr<T> sp;
public:
XCls() : sp(new T) { }
};
XCls<string, shared_ptr> p1;
Cls<double, unique_ptr> p2; //写法错误
Cls<int, weak_ptr> p3; //写法错误
XCls<long, auto_ptr> p4;
下面这个不是模板模板参数:第二个参数list因为已经绑定了int类型的模板参数,所以不是模板模板参数
template <class T, class Sequence = deque<T>>
class stack {
friend bool operateo== <> (cosnt stack&, const stack&);
friend bool operateo< <> (cosnt stack&, const stack&);
protected:
Sequence c;
......
};
stack<int> s1;
stack<int, list<int>> s2;