2009-10-12 65 views
5

我正在读取STL源代码。 虽然我理解stl_list.h中正在阅读的内容,但我想完全理解下面的代码片段(主要涉及模板语法,我认为)。关于C++模板语法(STL库源代码)的问题

模板

class _List_base { 
    ... 
    typedef typename _Alloc::template rebind<_List_node<_Tp> >::other _Node_Alloc_type; //(1). 

    ... 
    typedef _Alloc allocator_type; 
    get_allocator() const 
    { return allocator_type(*static_cast< 
          const _Node_Alloc_type*>(&this->_M_impl)); } // (2) 
    ... 
}; 

有人能解释为什么我们需要一个 “模板”,在线路(1)以下_Alloc? (并给出这条线的完整解释?)

有人可以解释为什么我们可以将_Node_Alloc_type投射到_Alloc在行(2)?

+3

你应该说明你在看什么特定的STL实现。虽然STL接口是标准化的,但实施方式因供应商而异。 – 2009-10-12 19:27:43

回答

12

需要使用template关键字将名称rebind识别为类模板。没有它,rebind可以被认为是一个变量或一个常数(在这种情况下,由于关键字typename)和以下<可以被解释为一个小于运算符。

这有点类似于typename关键字(这当然是识别other作为一种类型所必需的)。

每个分配器都需要提供一个名为rebind的元函数(即类模板),该函数返回相同的分配器,但返回不同的类型。换句话说,

Alloc<T>::rebind<U>::other 

名称类型相同

Alloc<U> 

你问题的第二部分是不困难的情况下多来回答。什么是_M_impl的类型?这种类型是如何定义的?

2

它看起来像std :: list的gcc实现。在这种情况下,上下文是:

struct _List_impl : public _Node_Alloc_type { ... }; 
_List_impl _M_impl; 

你忘了写成员函数的返回类型:

typedef _Alloc allocator_type; 
allocator_type 
get_allocator() const 
{ return allocator_type(*static_cast<const _Node_Alloc_type*>(&this->_M_impl)); } 

答:(1)

当添加节点在_Tp类型的列表中,真正需要分配的不是对象_Tp,而是包含_Tp(a _List_node<_Tp>)的列表节点。

所以std :: list需要能够分配一个_List_node<_Tp>,但它已经为_Tp提供了一个分配器。这就是模板typedef rebind派上用场的地方:它可以从类型T的分配器获得类型U的分配器。

使用此重新绑定,我们从_Alloc<_Tp>类型获得_Alloc<_List_node<_Tp> >


源文件为注释(2)中的答案:

// NOTA BENE 
// The stored instance is not actually of "allocator_type"'s 
// type. Instead we rebind the type to 
// Allocator<List_node<Tp>>, which according to [20.1.5]/4 
// should probably be the same. List_node<Tp> is not the same 
// size as Tp (it's two pointers larger), and specializations on 
// Tp may go unused because List_node<Tp> is being bound 
// instead. 
// 
// We put this to the test in the constructors and in 
// get_allocator, where we use conversions between 
// allocator_type and _Node_Alloc_type. The conversion is 
// required by table 32 in [20.1.5]. 

假设_Alloc的类型是一样的_Node_Alloc_type按C++标准;因此static_cast声明转换是合法的。