Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A question about C++ template syntax (STL library source code)

Tags:

c++

stl

I am reading STL source code right now. Though I understand the meat in what I am reading in stl_list.h, I want to fully understand the following snippet (mainly related to the template syntax, I think).

template

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)
  ...
};

Can someone explain why we need a "template" following _Alloc in line (1)? (and giving a full explanation of this line?)

Can someone explain why we can cast _Node_Alloc_type to _Alloc in line (2)?

like image 461
chen Avatar asked Oct 12 '09 19:10

chen


People also ask

What is Standard Template Library STL also describe its advantages?

A standard template library (STL) is a software library that extends C++ standard library's capabilities and provides a ready-made set of common classes for C++, including associative arrays and containers, which are used along with built-in and user-defined types that support elementary operations.

What are the three main components of STL?

STL is a library consisting of containers, algorithms, and iterators.

What is meant by the Standard Template Library How is it used?

The Standard Template Library, or STL, is a C++ library that consists of prebuilt functions and containers. It includes some prominent template classes for common data structures like vectors, stacks, queues, and some handy algorithmic functions like binary search to make programming easier.

What is the Standard Template Library and classify the components of STL?

The Standard Template Library (STL) is a software library originally designed by Alexander Stepanov for the C++ programming language that influenced many parts of the C++ Standard Library. It provides four components called algorithms, containers, functions, and iterators.


2 Answers

The template keyword is needed to identify the name rebind as a class template. Without it, rebind could be considered a variable or a constant (in this case a type due to the typename keyword) and the following < could be interpreted as a less-than operator.

This is somewhat similar to the typename keyword (which is of course necessary to identify other as a type).

Every allocator is required to provide a meta-function (i.e. a class template) called rebind that returns the same allocator but for a different type. In other words,

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

names the same type as

Alloc<U>

The second part of your question is difficult to answer without more context. What is the type of _M_impl? How is that type defined?

like image 143
avakar Avatar answered Sep 27 '22 19:09

avakar


It looks like the gcc implementation of std::list. In that case, the context is:

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

And you forgot to write the return type of the member function:

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

Answer for (1)

When adding a node in a list of type _Tp, what really needs to be allocated is not an object _Tp but a list node containing _Tp (a _List_node<_Tp>).

So the std::list needs to be able allocate a _List_node<_Tp> but it has been provided an allocator for _Tp. This is where the template typedef rebind comes in handy: it makes it possible to get an allocator for type U from an allocator for type T.

Using this rebind, we get an _Alloc<_List_node<_Tp> > from the type _Alloc<_Tp>.


Answer for (2) in the source file as comment:

// 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].

It is assumed that _Alloc's type is the same as _Node_Alloc_type as per the C++ Standard; hence the static_cast asserts the conversion is legal.

like image 24
Julien-L Avatar answered Sep 27 '22 21:09

Julien-L