Библиотека knigago >> Компьютеры: Языки и системы программирования >> Другие языки и системы программирования >> Симуляция частичной специализации


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

СЛУЧАЙНАЯ КНИГА

Соперница Аладдина.  Шахразада
- Соперница Аладдина

Жанр: Эротика

Год издания: 2012

Серия: Горячие ночи Востока

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

Симуляция частичной специализации
Книга - Симуляция частичной специализации.  Павел Кузнецов  - прочитать полностью в библиотеке КнигаГо
Название:
Симуляция частичной специализации
Павел Кузнецов

Жанр:

Другие языки и системы программирования

Изадано в серии:

неизвестно

Издательство:

RSDN Group

Год издания:

-

ISBN:

неизвестно

Отзывы:

Комментировать

Рейтинг:

Поделись книгой с друзьями!

Помощь сайту: донат на оплату сервера

Краткое содержание книги "Симуляция частичной специализации"

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

Читаем онлайн "Симуляция частичной специализации". [Страница - 2]

стр.

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

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

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

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

struct TrueType {char dummy_ [1];};

struct FalseType {char dummy_ [100];};


// Промежуточный класс PointerShim нужен,

// чтобы избежать ошибочной работы метафункции

// IsPointer в случае параметризации классом, в котором определен

// оператор преобразования к указателю.

struct PointerShim {

 PointerShim(const volatile void*);

};

// Т.к. функции ptr_discriminator на самом деле не вызываются, реализации не требуется.

TrueType ptr_discriminator(PointerShim);

FalseType ptr_discriminator(…);


// IsPointer‹T›::value == true, если T является указателем,

// IsPointer‹T›::value == false в противном случае.

template‹class T›

class IsPointer {

private:

 static T t_;

public:

 enum {

 value = sizeof(ptr_discriminator(t_)) == sizeof(TrueType)};

};


// Так как объект типа void создан быть не может,

// случай IsPointer‹void› должен обрабатываться отдельно.

template‹›

class IsPointer‹void› {

public:

 enum {value = false};

};

ПРЕДУПРЕЖДЕНИЕ Строго говоря, необходимо предоставлять не только специализацию для void, но и для соответствующих cv-квалифицированных разновидностей: const void, volatile void, const volatile void. Эти специализации опущены для краткости изложения.

ПРИМЕЧАНИЕ Функции, подобные ptr_discriminator, иногда называют дискриминирующими.

Техника основана на том, что во время компиляции выражения sizeof(ptr_discriminator(t_)) компилятор вынужден выбрать из двух перегруженных функций ptr_discriminator наиболее подходящую. В случае, если IsPointer‹T›::t_ является указателем, будет выбрана функция ptr_discriminator(PointerShim), возвращающая значение типа TrueType, и значение IsPointer‹T›::value обращается в true, т.к. sizeof(ptr_discriminator(PointerShim)) – sizeof(TrueType); в противном случае подходящей является функция ptr_discriminator(…)и значением IsPointer‹T›::value является false, т.к. sizeof(ptr_discriminator(…)) – sizeof(FalseType), а типы TrueType и FalseType выбраны таким образом, что sizeof(TrueType)!= sizeof(FalseType).

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

TrueType simple_ptr_discriminator(const volatile void*);

FalseType simple_ptr_discriminator(…);

Однако, в этом случае, метафункция IsPointer будет работать неверно, например, для таких классов:

struct C {

 operator int*() const {return 0;}

};

Так как класс C имеет операцию приведения к указателю, функция simple_ptr_discriminator может быть вызвана с любым объектом этого класса, и, следовательно, метафункция, построенная с использованием simple_ptr_discriminator, будет ошибочно определять подобные классы как указатели.

Пример. Для пущей ясности можно рассмотреть, как работает метафункция IsPointer‹T› на примере типа int. IsPointer‹int› разворачивается компилятором примерно в следующее:

// псевдокод

class IsPointer‹int› {

private:

 static int t_;

public:

 enum {value = sizeof(ptr_discriminator(t_)) == sizeof(TrueType)};

};

ptr_discriminator(PointerShim) для t_ не подходит, т.к. объект PointerShim может быть создан только из указателя. Следовательно, подходящей будет оставшаяся ptr_discriminator(…), которая возвращает FalseType. Значит, в данном случае выражение sizeof(ptr_discriminator(t_)) эквивалентно выражению sizeof(FalseType), значение которого по условию не равно sizeof(TrueType). Следовательно, IsPointer‹int›::value == false.

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

Использовать полученную метафункцию IsPointer‹T› для симуляции частичной специализации по виду аргумента шаблона можно примерно следующим образом:

// Реализация общего случая: T не является указателем.

template‹class T›

class C_ {

 //…

};


// Реализация случая, когда T является указателем.

template‹class T›

class C_ptr_ {

 //…

};


// Traits для случая, когда T является указателем

template‹bool T_is_ptr›

struct CTraits {

 template‹class T›

 struct Args {

  typedef C_ptr_‹T› Base;

 };

};


// Traits для случая, когда T не является указателем.

template‹›

struct CTraits‹false› {

 template‹class T› struct Args {

  typedef C_‹T› Base;

 };

};


// Класс, предназначенный для использования клиентами.

template‹class T›

class C: public CTraits‹IsPointer‹T›::value›::template Args‹T›::Base {

 //…

};

--">
стр.

Оставить комментарий:


Ваш e-mail является приватным и не будет опубликован в комментарии.