Что делает (шаблон) rebind <> делать?

пытаясь узнать больше о том, как фактически реализована стандартная библиотека, я просматриваю все контейнеры в visual studio.. Здесь я вижу какую-то любопытную структуру:

В некотором базовом классе a std::list<> Найден следующий typedef

typedef typename _Alloc::template rebind<_Ty>::other _Alty;

Где "_Alloc" соответствует аргументу шаблона распределителя (и _Ty содержащемуся типу). Мне трудно найти хорошее объяснение этого "ключевого слова". Самое лучшее, что я нашел до сих пор, это то, что он является частью интерфейса распределителя. Хотя даже cppreference не очень хорошо объясняет это.

Что делает это template rebind<>? И почему это необходимо в этом месте?

Ответ 1

Шаблон _Alloc используется для получения объектов определенного типа. Контейнер может иметь внутреннюю потребность в распределении объектов другого типа. Например, когда у вас есть std::list<T, A>, распределитель A предназначен для выделения объектов типа T, но std::list<T, A> на самом деле нужно выделить объекты некоторого типа node. Вызов node типа _Ty, std::list<T, A> должен получить доступ к распределителю для объектов _Ty, который использует механизм распределения, предоставляемый A. Использование

typename _A::template rebind<_Ty>::other

указывает соответствующий тип. Теперь в этой декларации есть несколько синтаксических раздражений:

  • Так как rebind является шаблоном-членом _A, а _A является аргументом шаблона, rebind становится зависимым именем. Чтобы указать, что зависимым именем является шаблон, его необходимо префикс template. Без ключевого слова template < будет считаться менее оператором.
  • Имя other также зависит от аргумента шаблона, т.е. это также зависимое имя. Чтобы указать, что зависимое имя является типом, требуется ключевое слово typename.

Ответ 2

rebind предназначен для выделения памяти для типа, который отличается от типа элемента реализуемого контейнера. Возьмите эту статью MSDN:

Например, если задан объект-распределитель al типа A, вы можете выделить объект типа _Other с выражением:

A::rebind<Other>::other(al).allocate(1, (Other *)0)

Или вы можете назвать его тип указателя, написав тип:

A::rebind<Other>::other::pointer

Ответ 3

пожалуйста, проверьте http://www.cplusplus.com/reference/memory/allocator/

вы увидите

rebind <... > на самом деле является членом распределителя классов, который является частью STL без предоставления исходного кода реализации.

как вы видите, rebind <... > также является шаблоном, и он заслуживает того типа, чтобы класс распределителя знал, что находится в моем элементе обратной связи.

вернемся к вашему утверждению: typedef typename _Alloc:: template rebind < _Ty > :: other _Alty; если вы опустили шаблон: typedef typename _Alloc:: rebind < _Ty > :: other _Alty; вы можете легко понять, что rebind является членом _Alloc, но компилятор не может понять.

Учитывая характер повторной привязки, являющийся шаблоном, требуется повторная привязка шаблона < _Ty > и обрабатывается как целое не две части.

Ответ 4

Пример в коде stdС++:/usr/include/4.8/ext/new_allocator.h

rebind определяется как член структуры класса распределителя; эта структура определяет член другой, который определяется как экземпляр распределителя, специализированного для другого типа аргумента (член другой определяет класс распределителя, который может создавать другой тип объекты)

 template<typename _Tp>
    class new_allocator
    {
    public:
      ...
      template<typename _Tp1>
        struct rebind
        { typedef new_allocator<_Tp1> other; };

Когда он используется:

  typedef typename _Alloc::template rebind<_Tp>::other _Tp_alloc_type;

тип распределителя ссылается как

  typename _Alloc::template rebind<_Tp>::other 

Теперь typedef используется для определения _Tp_alloc_type, который затем может использоваться как более короткое имя для одной и той же вещи.

Пример использования в std:: list, где внутренний список node также нуждается в его распределителе, который переопределяется из распределителя аргументов.