Симуляция частичной специализации - [2]
>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 {
> //…
>};
Ограничения
Приведенная техника симуляции частичной специализации обладает некоторыми ограничениями по сравнению с «настоящей» частичной специализацией шаблонов классов.
Одним из наиболее заметных ограничений является то, что дискриминирующие функции, применяющиеся при создании многих метафункций, требуют объявления переменной, поэтому не работают с абстрактными классами. Например, в случае с IsPointer‹T› объявляется статическая переменная t_. Несмотря на то, что ее определение не требуется, специализация шаблона IsPointer‹T› абстрактным классом приведет к ошибке компиляции. По этой же причине приходится предоставлять специализации шаблонов метафункций для void.
Другим ограничением является то, что некоторые метафункции, построенные с использованием дискриминирующих функций, например, IsConst‹T›, IsVolatile‹T›, IsReference‹T› и т.п., некорректно работают в случае, если T имеет квалификаторы и const и volatile одновременно (например, const volatile int&). Существующая реализация метафункций IsConst‹T› и IsVolatile‹T› без «настоящей» частичной специализации сводится к использованию соответствующих дискриминирующих функций:

Java Enterprise Edition (Java EE) остается одной из ведущих технологий и платформ на основе Java. Данная книга представляет собой логичное пошаговое руководство, в котором подробно описаны многие спецификации и эталонные реализации Java EE 7. Работа с ними продемонстрирована на практических примерах. В этом фундаментальном издании также используется новейшая версия инструмента GlassFish, предназначенного для развертывания и администрирования примеров кода. Книга написана ведущим специалистом по обработке запросов на спецификацию Java EE, членом наблюдательного совета организации Java Community Process (JCP)

Книга посвящена разработке программ для мобильных устройств под управлением операционной системы Android. Рассматривается создание приложений с использованием системных компонентов и служб Android. Приведены базовые данные о структуре приложений, об основных классах и их методах, сопровождаемые примерами кода. Часть 1 содержит шесть глав, описывающих основные принципы создания приложений, пользовательский интерфейс, полномочия приложений, а так же базовые классы: Activity, Intent, Fragment. Книга предназначена для программистов, владеющих языком программирования Java и желающих освоить написание приложений, работающих под ОС Android.

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

Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.