关于C ++模板语法的问题(STL库源代码)

时间:2009-10-12 19:07:09

标签: c++ stl

我正在阅读STL源代码。 虽然我理解stl_list.h中的内容,但我想完全理解以下代码片段(我认为主要与模板语法有关)。

模板

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之后使用“模板”吗? (并对这一行给出完整的解释?)

有人可以解释为什么我们可以在行(2)中将_Node_Alloc_type转换为_Alloc吗?

2 个答案:

答案 0 :(得分:12)

需要template关键字来将名称rebind标识为类模板。没有它,rebind可以被视为变量或常量(在这种情况下是由typename关键字引起的类型),并且后面的<可以被解释为小于运算符。

这有点类似于typename关键字(当然需要将other标识为类型)。

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

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

的名称与

相同
Alloc<U>

如果没有更多背景,你的问题的第二部分很难回答。 _M_impl的类型是什么?该类型是如何定义的?

答案 1 :(得分: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的列表节点(_List_node<_Tp> )。

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

使用此重新绑定,我们会从_Alloc<_List_node<_Tp> >类型中获得_Alloc<_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].

根据C ++标准,假设_Alloc的类型与_Node_Alloc_type相同;因此static_cast断言转换是合法的。