Частичная специализация синтаксиса путаница - PullRequest
1 голос
/ 17 февраля 2012

Чтобы определить специализацию, которая используется для каждого вектора указателей и только для векторов указателей, нам нужна частичная специализация:

 template <class T> class  Vector <T *> : private Vector<void *> {
 public:
      typedef Vector<void*> Base;
      Vector(): Base() {}
      explicit Vector(int i) : Base(i ) {}
      T *& elem(int i ) { return static_cast <T *&> (Base::elem(i)); }
      T *& opeator[](int  i) { return static_cast <T *&>(Base::operator[](i )); }
      //...
 };

Это определение вызывает у меня головокружение.Это связано с частичной специализацией, но я не понимаю синтаксис.private Vector<void *> часть определения для меня выглядит как родительский класс.

  1. Почему бы не указать Vector <void *> в template <class T> class Vector <void *>.
  2. Было бы здорово, если бы кто-нибудь смог разбить часть определения,(извините, если спросить слишком много)

Ответы [ 4 ]

2 голосов
/ 17 февраля 2012

Забудьте о наследовании, которое не имеет никакого отношения к рассматриваемой проблеме.

Частичная специализация означает, что вы создаете новый шаблон из существующего, который является более специализированным, но все же общим, путем сопоставления с более узким шаблоном. Общая схема вашего примера выглядит следующим образом:

template <typename T> class Foo;      // primary template

template <typename U> class Foo<U*>;  // partial specialization

template <> class Foo<fool>;          // full specialization

Первая строка является основным шаблоном и соответствует всему , который не соответствует более специализированной форме. Третья строка определяет фактический тип (не шаблон!) Foo<fool> (для некоторого данного типа fool). Средняя линия, с другой стороны, все еще является шаблоном, но она соответствует только типу формы T = U *, то есть указателю:

 Foo<char> x;   // uses primary template with T = char
 Foo<fool> y;   // uses full specialization (nothing to be matched)
 Foo<int*> z;   // uses partial specialization, matching U = int

О Vector<void*>: просто получается, что автор решил определить частично специализированный Vector<U*> как производный от фиксированного класса Vector<void*> (который должен был бы быть полностью специализированным в другом месте).

0 голосов
/ 17 февраля 2012

Кажется, что автор кода хочет использовать тот факт, что код для разных типов указателей идентичен.Вероятно, это просто преждевременная оптимизация для уменьшения размера кода или «раздувания кода».Скорее всего, идея заключается в том, что каждый новый тип указателя будет добавлять только слой static_cast к коду пустого указателя.

0 голосов
/ 17 февраля 2012

По сути, это делает члены Vector<Ptr> для любого типа указателя вперед Vector<void*> (используя комбинацию наследования и явных базовых вызовов плюс приведение).Это не позволяет компилятору создавать много одинаковых версий одного и того же кода, отличающихся только типом указателя, что, возможно, экономит место в конечном исполняемом файле (хотя большинство компоновщиков достаточно умен, чтобы объединять идентичные функции, см., Например, «свертывание COMDAT»)

В соответствии со Стандартом это проблематично, поскольку указатели не имеют одинаковых ограничений на выравнивание.Не все указатели на объекты обязательно имеют одинаковый размер в соответствующей реализации.На самом деле, я очень удивлен, что компилятор вообще принимает static_cast<T*&>(a_void_ptr).Разумеется, статическое приведение между void* и T* допускается, но это касается типов ссылки на указатель, которые не связаны.Это должно потребовать reinterpret_cast.

0 голосов
/ 17 февраля 2012

Ваш вопрос касается специализации шаблона, и вот что здесь происходит.

Это определение класса шаблона для Vector<T>, специализирующегося для типа указателя T. Предположительно, вы определили Vector<T> шаблон в другом месте, так что этот код специализирует его только в тех случаях, когда T является указателем.Следовательно, Vector<T*>.

Поскольку это специализация, Vector<T*> происходит от вектора 'base-template', который является Vector<void *>.Другой код, который не описан в вашем примере, будет обрабатывать особенности работы с типом указателя в качестве содержащихся данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...