C++的模板(三):向模板传递模板

类模板是一种不完全的类型。它需要绑定参数,才能转化成实际的类型。这个过程叫做实例化。模板的参数必须是常数,或者类型。那么如果需要向模板传递模板该怎么办呢?

STL采用了rebind的办法。这是摘自STL allocator内存分配器的代码:

  template<typename _Tp>
    class new_allocator
    {
    
    
    public:
      typedef size_t     size_type;
      typedef ptrdiff_t  difference_type;
      typedef _Tp*       pointer;
      typedef const _Tp* const_pointer;
      typedef _Tp&       reference;
      typedef const _Tp& const_reference;
      typedef _Tp        value_type;

      template<typename _Tp1>
        struct rebind
        {
    
     typedef new_allocator<_Tp1> other; };

      new_allocator() throw() {
    
     }

      new_allocator(const new_allocator&) throw() {
    
     }

      template<typename _Tp1>
        new_allocator(const new_allocator<_Tp1>&) throw() {
    
     }

      ~new_allocator() throw() {
    
     }

      pointer
      address(reference __x) const {
    
     return &__x; }

      const_pointer
      address(const_reference __x) const {
    
     return &__x; }

      // NB: __n is permitted to be 0.  The C++ standard says nothing
      // about what the return value is when __n == 0.
      pointer
      allocate(size_type __n, const void* = 0)
      {
    
     return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); }

      // __p is not permitted to be a null pointer.
      void
      deallocate(pointer __p, size_type)
      {
    
     ::operator delete(__p); }

      size_type
      max_size() const throw()
      {
    
     return size_t(-1) / sizeof(_Tp); }

      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 402. wrong new expression in [some_] allocator::construct
      void
      construct(pointer __p, const _Tp& __val)
      {
    
     ::new(__p) _Tp(__val); }

      void
      destroy(pointer __p) {
    
     __p->~_Tp(); }
    };

new_allocator实例化了之后,它通过调用new_allocator::rebind::other又还原了这块代码的模板特性。在STL红黑树实现中,对传入数据类型,添加指针之后,用rebind::other来分配node内存。这里的allocator模板和rebind::other实际是一回事。

那么,可不可以在template 声明中直接传模板呢?比如代码这样写:
template < class T, template < class U > class allocator>

调试发现,这样写gcc是能够接受的。

#include <stdio.h>

#include <ext/new_allocator.h>

template <class T, template<class U>class Alloc=__gnu_cxx::new_allocator>
struct list {
    
    
        T  t;
        list *next;

        void insert(const T &t);
};

template <class T, template<class U>class Alloc>
void list<T,Alloc>:: insert(const T& t)
{
    
    
        list *node;
        Alloc<list> al;
        Alloc<T> at;
        node = al.allocate(1);
        at.construct(&node->t, t);
        node->next=next;
        next = node;
}

int main()
{
    
    
        list<int> l;
        l.t=0;
        l.next=0;
        l.insert(1);
        l.insert(2);
        l.insert(3);
        l.insert(4);
        l.insert(5);
        list<int> *p;
        p = &l;
        while(p) {
    
    
                printf("%d->", p->t);
                p= p->next;
        }
        printf("END\n");
}

Guess you like

Origin blog.csdn.net/aaasssdddd96/article/details/108143937