Специализация шаблонов псевдонимов

Могут ли шаблоны псевдонимов (14.5.7) быть явно специализированными (14.7.3)?

Мой стандарт-fu меня сбивает, и я не могу найти компилятор для тестирования.

Текст «когда идентификатор шаблона ссылается на специализацию шаблона псевдонимов» подразумевает « да» , но тогда, как представляется, этот пример ссылается на что-то другое, подразумевая, что нет .

NB. Я работаю от n3242, один позади FDIS, в котором заголовок этого раздела – «Шаблоны псевдонимов». Лол.

То, что Стандарт означает «специализация», – это преобразование общего шаблона в более специализированный объект. Например, создание экземпляра шаблона classа, не являющегося членом, дает class, который больше не является шаблоном. Термин «специализация» имеет два раза и может ссылаться на сгенерированную специализацию (которая является специализацией, которая была создана, возможно, из частичной специализации) и явной специализации (о чем вы говорили).

Шаблоны псевдонимов не создаются и не имеют специализации. Ничто не может создать. Вместо этого, когда за их именем следует список аргументов шаблона, обозначаемый тип – это тип, который вы получаете, заменяя имя и список аргументов типом alias’ed, заменяя все ссылки на параметры шаблона аргументами, приведенными в списке аргументов. То есть, вместо того, чтобы специализироваться на том, что он является псевдонимом, сам шаблон псевдонимов служит псевдонимом, без необходимости создавать что-либо. Эта замена выполняется очень рано. Рассматривать:

template using ref = T&; template void f(ref x) { x = 10; } int main() { int a; f(a); return a; /* 10 */ } 

Замена выполняется в момент, когда назван ref (такие имена используются для обозначения специализированных шаблонов classов или функций, поэтому спецификация описывает такие имена для «ссылки на специализацию шаблона псевдонимов»). То есть параметр f имеет тип T& , и, следовательно, T можно вывести. Это свойство предотвращает явные или частичные специализации шаблонов псевдонимов. Потому что для того, чтобы выбрать правильную специализацию ref , нужно знать T Но для того, чтобы узнать это, нужно сравнить ref с типом аргумента, чтобы вывести T Он обобщен в статье N1406 «Предлагаемое дополнение к C ++: шаблоны Typedef» , раздел 2.2

2.2 Главный выбор: специализация против всего остального

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

  1. Шаблон typedef сам по себе не является псевдонимом; только (возможно, специализированные) экземпляры шаблона typedef являются псевдонимами. Этот выбор позволяет нам специализироваться на шаблонах typedef.

  2. Шаблон typedef сам по себе является псевдонимом; он не может быть специализированным. Этот выбор позволил бы:

    • вычет по параметрам функции шаблона typedef (см. 2.4)
    • декларация, выраженная с использованием шаблонов typedef, будет такой же, как декларация без шаблонов typedef (см. 2.5)
    • Шаблоны typedef для соответствия параметрам шаблона шаблона (см. 2.6)

Следует отметить, что цитируемый документ, который одобряет вариант 1, не попал в C ++ 0x.


EDIT: Потому что вы отчаянно хотите, чтобы цитата из спецификации говорила так явно. 14.5p3 – это тот, который делает

Поскольку декларация alias не может объявить идентификатор шаблона, невозможно частично или явно специализировать шаблон псевдонимов.

Бьярне говорит :

Специализация работает (вы можете использовать набор специализаций, но вы не можете специализировать псевдоним)

И, хотя это не явное правило, в следующем списке отсутствуют «шаблоны псевдонимов» в 14.7.3 / 1:

Явная специализация любого из следующего:

  • шаблон функции
  • шаблон classа
  • функция-член шаблона classа
  • статический элемент данных шаблона classа
  • class участника шаблона classа
  • шаблон classа участника шаблона classа или classа
  • шаблон элемента-члена шаблона classа или classа

может быть объявлено […]

Я думаю, что это лучшая гарантия, которую вы получите.

Я не уверен, понимаю ли я этот вопрос, но в любом случае я попытался имитировать специализацию шаблона псевдонимов.

Я предполагаю, что идея состоит в том, чтобы ограничить шаблон псевдонима определенным (тип с сопоставлением с образцом); то, что мы привыкли делать с таким кодом:

 template struct old_style; template struct old_style >{ typedef typename std::vector::value_type type; }; 

(это просто пример, есть другой способ извлечь value_type общего std::vector ).

Теперь к псевдонимам:

 template using new_style = typename Vector::value_type; 

Он выполняет ту же работу, но это не заменяет old_stype<...>::type , поскольку он не является ограничивающим. Первая попытка иметь идеальную замену псевдонимов – это гипотетический код:

 //template using new_style2; // error already here //template using new_style2 > = typename Vector::value_type; 

К сожалению, он не компилируется (теоретически из-за номинальных причин, изложенных в других ответах и ​​стандарте, на практике, я думаю, нет основополагающих причин для этого ограничения). К счастью, можно отбросить старомодный метод struct::type , чтобы использовать его только для использования новой функции шаблона псевдонимов для пересылки работы,

 template struct new_style2_aux; template struct new_style2_aux >{ typedef typename std::vector::value_type type; }; template using new_style2 = typename new_style2_aux::type; 

Можно сделать это автоматически с define

 #define SPECIALIZED_ALIAS_TEMPLATE(NamE, Pattern_arG, PatterN_expR, DefinitioN) \ template struct NamE ## _aux; \ template struct NamE ## _aux{ \ typedef DefinitioN type; \ }; \ template using NamE = typename NamE ## _aux< NamE ## _dummy >::type; 

Который может использоваться как:

 SPECIALIZED_ALIAS_TEMPLATE(new_style3, class T, std::vector, typename std::vector::value_type); 

Если требуется произвольное число специализаций (или не локально в коде), нужно использовать более сложное define в двух частях: одно для объявления и одно для специализации (как и должно быть):

 #define DECLARE_ALIAS_TEMPLATE(NamE)\ template struct NamE ## _aux;\ template using NamE = typename NamE ## _aux< NamE ## _dummy >::type; #define SPECIALIZE_ALIAS_TEMPLATE(NamE, Pattern_arG, PatterN_expR, DefinitioN)\ template struct NamE ## _aux{ \ typedef DefinitioN type; \ }; 

Используется следующим образом:

 DECLARE_ALIAS_TEMPLATE(new_style4); SPECIALIZE_ALIAS_TEMPLATE(new_style4, class T, std::vector, typename std::vector::value_type); SPECIALIZE_ALIAS_TEMPLATE(new_style4, class T, std::set, typename std::set::value_type); 

Весь код, указанный выше, можно скопировать и вставить для проверки:

 #include #include // ... paste code above // int main(){ old_style >::type a; // is a double // old_style >::type a; // error (should work only for std::vector) new_style2 > b; // is double // new_style2 > c; // error (should work only for std::vector) new_style3 > d; // is double // new_style3 > d; // error (should work only for std::vector) new_style4 > e; // is double new_style4 > f; // is double, this is another specialization return 0; } 

Извините, если это не то, что вы ищете. Я считаю, что он может использоваться с вариационными шаблонами и с дополнительными аргументами шаблона (по специализации), но не проверял его.

Усовершенствования приветствуются.

Если вам нужно поточечное отображение от чего-то к типу, это работает (в gcc 4.8.3):

 // int to type mapper template struct BitsToTypesMap { typedef void TYPE; // default }; // pointwise mapping template<> struct BitsToTypesMap<32>{ typedef int TYPE; }; template<> struct BitsToTypesMap<8>{ typedef char TYPE; }; template<> struct BitsToTypesMap<16>{ typedef short TYPE; }; // cute wrapping template using MyScalarType = typename BitsToTypesMap::TYPE; // TEST template MyScalarType Add ( MyScalarType x, MyScalarType y ) { return x+y; } int test() { MyScalarType<32> i=Add<32>(1,2); MyScalarType<8 > b=Add<8 >(1,2); MyScalarType<16> s=Add<16>(1,2); return i+b+s; } 
  • Общая библиотека C ++ с шаблонами: ошибка неопределенных символов
  • Как передать функцию шаблона в списке аргументов шаблона
  • Может ли шаблон функции члена classа C ++ быть виртуальным?
  • с использованием шаблона extern (C ++ 11)
  • Идентификация примитивных типов в шаблонах
  • Неявное преобразование при перегрузке операторов для classов шаблонов
  • HTML5: Почему мой атрибут oninvalid позволяет шаблону выйти из строя?
  • Полезные шаблоны кода Java Eclipse
  • Сведения о создании шаблона компиляторов GCC и MS
  • Метапрограммирование: отказ определения функции Определяет отдельную функцию
  • Как явным образом создаю экземпляр функции шаблона?
  • Давайте будем гением компьютера.