C++【侯捷】——— 成员模板、模板特化、模板模板参数

C++【侯捷】——— 成员模板、模板特化、模板模板参数


自己写的程序最好用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;
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值