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

на главную - закладки

Жанры

Поделиться:

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

Шрифт:

Введение

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

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 в данном случае обязательно, хотя некоторые компиляторы и позволяют его опускать.

Использование

Метапрограммирование и метафункции

Прежде чем перейти к изложению дальнейшего материала, полезно ввести понятия метапрограммирования и метафункции. Если внимательнее посмотреть на то, что происходит, когда компилятор встречает пример, подобный наследованию класса Matrix от MatrixTraits‹T›::…::Base, можно заметить, что фактически это является программированием компилятора. То есть, в данном случае компилятор как бы получает инструкцию: «если тип шаблона является типом float, то считать базовым классом Matrix_float_‹›, в противном случае – Matrix_‹›. Это можно рассматривать как программирование вычислений времени компиляции. Подобные техники иногда называют метапрограммированием шаблонами или просто метапрограммированием, а шаблоны, подобные MatrixTraits, – метафункциями.

Частичная специализация по виду аргумента шаблона

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

template‹class T›

class С {

 //…

};

template‹class T›

class С‹T*› {

 //…

};

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

template‹class T›

struct IsPointer {

 static const bool value =…;

};

где IsPointer‹T›::value принимает значения true или false в зависимости от того, является ли тип T указателем.

ПРИМЕЧАНИЕ Так как некоторые компиляторы не поддерживают должным образом определение статических констант времени компиляции в теле класса, эта метафункция может быть переписана эквивалентным образом с использованием enum.

Метафункция IsPointer‹T›

Задачу построения подобной метафункции решили в 2000 году сотрудники Adobe Systems Incorporated Мэт Маркус и Джесс Джонс. Суть решения сводится к использованию выражения вызова перегруженных функций внутри sizeof:

// Типы TrueType и FalseType могут быть определены произвольным образом,

// главное чтобы выполнялось условие: sizeof(TrueType)!= sizeof(FalseType).

struct TrueType {char dummy_ [1];};

Комментарии:
Популярные книги

Зеркало силы

Кас Маркус
3. Артефактор
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Зеркало силы

Имперец. Земли Итреи

Игнатов Михаил Павлович
11. Путь
Фантастика:
героическая фантастика
боевая фантастика
5.25
рейтинг книги
Имперец. Земли Итреи

Бразилия

Сигалова Мария
Справочная литература:
путеводители
5.00
рейтинг книги
Бразилия

Имперец. Том 5

Романов Михаил Яковлевич
4. Имперец
Фантастика:
попаданцы
альтернативная история
аниме
6.00
рейтинг книги
Имперец. Том 5

Геном хищника. Книга четвертая

Гарцевич Евгений Александрович
4. Я - Легенда!
Фантастика:
боевая фантастика
рпг
попаданцы
5.00
рейтинг книги
Геном хищника. Книга четвертая

Кодекс Охотника. Книга XXXIV

Винокуров Юрий
34. Кодекс Охотника
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XXXIV

Камень. Книга вторая

Минин Станислав
2. Камень
Фантастика:
фэнтези
8.52
рейтинг книги
Камень. Книга вторая

Убивать, чтобы жить

Бор Жорж
1. УЧЖ
Фантастика:
героическая фантастика
боевая фантастика
рпг
5.25
рейтинг книги
Убивать, чтобы жить

Великий род

Сай Ярослав
3. Медорфенов
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Великий род

Схрон

Головачев Василий Васильевич
2. Смутное время
Фантастика:
научная фантастика
8.08
рейтинг книги
Схрон

Егерь. Столичный гамбит

Скиба Николай
4. Зверолов
Фантастика:
рпг
уся
фэнтези
фантастика: прочее
попаданцы
6.60
рейтинг книги
Егерь. Столичный гамбит

Дикое поле

Веденеев Василий Владимирович
Приключения:
исторические приключения
8.29
рейтинг книги
Дикое поле

Вернувшийся: Новая жизнь. Том I

Vector
1. Вернувшийся
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Вернувшийся: Новая жизнь. Том I

Старый, но крепкий 5

Крынов Макс
5. Культивация без насилия
Фантастика:
рпг
аниме
уся
фэнтези
5.00
рейтинг книги
Старый, но крепкий 5
Спасибо за голос.