Что делает (шаблон) 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 также нуждается в его распределителе, который переопределяется из распределителя аргументов.