указателя. Следовательно, подходящей будет оставшаяся 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› без «настоящей» частичной специализации сводится к использованию соответствующих дискриминирующих функций:

TrueType const_discriminator(const volatile void*);

FalseType const_discriminator(volatile void*);

template‹class T›

struct IsConst {

private:

 static T t_;

public:

 enum {value = sizeof(const_discriminator(&t_)) == sizeof(TrueType)};

};

template‹›

class IsConst‹void› {

public:

 enum {value = false};

};

TrueType volatile_discriminator(const volatile void*);

FalseType volatile_discriminator(const void*);

template‹class T›

struct IsVolatile {

private:

 static T t_;

public:

 enum {value = sizeof(volatile_discriminator(&t_)) – sizeof(TrueType)};

};

template‹›

class IsVolatile‹void› {

public:

 enum {value = false};

};

Очевидно, что эти метафункции не работают, если в качестве аргумента им передан тип имеющий как

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату