Почему параметр шаблона шаблона не допускает "typename" после списка параметров

Тип шаблона шаблона?

При использовании синтаксиса шаблона шаблона, как в template <template <typename> class T>, необходимо использовать ключевое слово class, поскольку использование typename приводит к ошибке в следующих строках:

ошибка: параметр шаблона шаблона требует "класс" после списка параметров

В остальном ключевые слова typename и class взаимозаменяемы в основном случае объявления параметра шаблона.

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

template <template <typename> class T> // 'class' keyword required.
struct Foo {
    using type = T<int>;
};

template <typename T>
using type = T (*)();

using func_ptr_t = Foo<type>::type;

Что за этим стоит?

  • Есть ли какая-то конкретная причина, почему typename не разрешен в объявлениях шаблонов шаблонов?
  • Говорит ли что-нибудь об этом стандарт C ++?

person Snps    schedule 06.06.2014    source источник
comment
Есть предложение разрешить typename прямо сейчас.   -  person chris    schedule 06.06.2014
comment
Меня больше удивляет то, что он не позволяет struct.   -  person BЈовић    schedule 06.06.2014
comment
GCC 5 теперь позволяет использовать имя типа в параметре шаблона шаблона.   -  person zangw    schedule 09.12.2014
comment
возможный дубликат параметров шаблона шаблона, почему принудительный класс?   -  person Walter    schedule 04.04.2015


Ответы (2)


Краткий ответ: так сказано в стандарте.

Более подробный ответ: до стандартизации шаблоны C ++ требовали ключевого слова class для всех параметров шаблона. Однако, чтобы подчеркнуть тот факт, что шаблоны также могут быть неклассового (то есть встроенного) типа, было введено альтернативное ключевое слово typename. Однако в C ++ 98 параметры шаблон-шаблон могли быть только типа класса, и это было причиной того, что ключевое слово typename не было добавлено в этом контексте.

Откройте для себя C ++ 11 и его новую функцию псевдонимы шаблонов, в которых теперь также представлены шаблоны, не относящиеся к классу, и, следовательно, параметры шаблона-шаблона, не являющиеся классами:

template<typename T> struct A {};
template<typename T> using B = int;

template<template<typename> class X> struct C;
C<A> ca; // ok
C<B> cb; // ok, not a class template
template<template<typename> typename X> struct D; // error, cannot use typename here

Приведенный выше пример был взят из текущего предложения C ++ 1z N4051 под названием Разрешить typename в параметре шаблона шаблона и предлагает разрешить именно это.

Clang 3.5 SVN теперь поддерживает это с флагом -std=c++1z.

person TemplateRex    schedule 06.06.2014
comment
Visual Studio 2015 теперь тоже поддерживает N4051 (только что проверено). - person Dwayne Robinson; 26.08.2015

Я ищу рациональное объяснение этого ограничения [...]

До появления C ++ 11 единственными шаблонами, которые можно было передать в параметр шаблона шаблона, были шаблоны class. Вот почему было принудительно использовано ключевое слово class. Кроме того, ключевое слово typename означает, что параметр шаблона является заменой произвольного типа, а не шаблона, поэтому использование typename в этом контексте просто размывает границу между названия типов и (класс) шаблонов. Это понятно.

В настоящее время такими аргументами могут быть имена шаблонов классов или шаблоны псевдонимов, и, поскольку они даже не подключены удаленно, принудительное использование ключевого слова class более или менее устарело. Предложение N4051 предлагает изменить это с помощью C ++ 1Z.

person Columbo    schedule 31.05.2014
comment
Этот ответ был дан (31 мая 2014 г.) до того, как был задан вопрос (6 июня 2014 г.). Как такое возможно ??? - person Walter; 03.04.2015
comment
@Walter Он был объединен из stackoverflow.com/questions/23965105/. - person T.C.; 04.04.2015
comment
@ T.C. Хм. Почему при слиянии первый вопрос был помечен как повторяющийся (и, следовательно, голосование по нему отключено), а не второй? Обратите внимание, что существует даже более старый вопрос такое же содержание. Не следует ли его тоже объединить? - person Walter; 04.04.2015