Симуляция частичной специализации - П Кузнецов

Симуляция частичной специализации

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

Читать Симуляция частичной специализации (Кузнецов) полностью

Введение

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

>template‹class T, int Rows, int Columns›

>class Matrix {

> //…

>};

Предположим, в процессе разработки выяснилось, что производительность программы неудовлетворительна, и узким местом является функция умножения матриц с элементами типа float, и что эту проблему можно решить путем использования intrinsic-функций процессора. При наличии соответствующей поддержки компилятора это легко можно сделать при помощи так называемой частичной специализации шаблонов классов:

>template‹int Rows, int Columns›

>class Matrix‹float, Rows, Columns› {

> //…

>};

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

Техника симуляции

Естественным первым шагом будет вынести различающуюся функциональность Matrix‹› в два базовых класса: Matrix_‹›, реализующий общий случай, и Matrix_float_‹› для специфики Matrix‹float,…›.

>template‹class T, int Rows, int Columns›

>class Matrix_ {

> //…

>};


>template‹int Rows, int Columns› class Matrix_float_ {

> //…

>};

Таким образом, проблема сведется к тому, чтобы класс Matrix‹T, Rows, Columns› наследовался от Matrix_‹T, Rows, Columns› или Matrix_float_‹Rows, Columns›, в зависимости от того, является ли параметр T шаблона Matrix‹› типом float. Решение этой задачи и является главным «фокусом» данной техники.

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

>template‹class T›

>struct MatrixTraits {

> template‹int Rows, int Columns›

> struct Dimensions {

>  typedef Matrix_‹T, Rows, Columns› Base;

> };

>};


>template‹›

>struct MatrixTraits‹float› {

> template‹int Rows, int Columns›

> struct Dimensions {

>  typedef Matrix_float_‹Rows, Columns› Base;

> };

>};

Теперь осталось просто унаследовать Matrix‹› от соответствующего класса MatrixTraits‹›::…::Base.

>template‹class T, int Rows, int Columns›

>class Matrix: public MatrixTraits‹T›::template Dimensions‹Rows, Columns›::Base {

> //…

>};

ПРИМЕЧАНИЕ Согласно текущей версии стандарта, использование ключевого слова template при квалификации вложенного шаблона Dimensions в данном случае обязательно, хотя некоторые компиляторы и позволяют его опускать.