Почему структуры не допускаются в определениях шаблонов? - PullRequest
4 голосов
/ 26 марта 2010

Следующий код выдает ошибку error: ‘struct Foo’ is not a valid type for a template constant parameter:

template <struct Foo>
struct Bar {

};

Почему это так?

template <class Foo>
struct Bar {

};

прекрасно работает и даже принимает структуру в качестве аргумента.

Ответы [ 4 ]

9 голосов
/ 26 марта 2010

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

Я полагаю, что Страуструп (и тот, от кого он мог бы получить информацию) решил, что нет необходимости включать struct в качестве ключевого слова a, чтобы указать параметр шаблона типа, поскольку не было необходимости обратной совместимости с C.

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


Edit:

Оказывается, история больше похожа (из записи в блоге Стэна Липпмана ):

Причина двух ключевых слов исторические. В оригинальном шаблоне Спецификация, Страуструп повторно использовал существующее ключевое слово класса, чтобы указать параметр типа, а не вводить новое ключевое слово, которое может, конечно, сломаться существующие программы. Это не было новое ключевое слово не рассматривалось - просто что это не было сочтено необходимым учитывая его потенциальное нарушение. И вверх до стандарта ISO-C ++, это было единственный способ объявить тип параметр.

Повторное использование существующих ключевых слов всегда сеять растерянность То, что мы нашли, это что начинающие были [интересно] будет ли использование класса ограничен или ограничен тип аргументы, которые пользователь может указать, чтобы быть типы классов, а не, скажем, встроенный или указатель типа. Так что было какое-то чувство, что не имея ввел новое ключевое слово было ошибка.

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

...

Комитет решил, что новый Ключевое слово было просто билет, чтобы получить компилятор от своей неудачной одержимости с выражениями. Новое ключевое слово было самоописываемое имя.

...

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

4 голосов
/ 26 марта 2010

Краткий ответ: template <class Foo> даже принимает union или double - тем не менее, ни один не разрешен вместо class. Однако typename есть. Именно так был определен синтаксис.

Несколько более длинный ответ: когда шаблоны для C ++ были «изобретены», в этом месте требовалось ключевое слово, говорящее о том, что следующим идентификатором будет имя типа. Было решено повторно использовать существующее ключевое слово class. Это немного сбивало с толку, но есть общее нежелание вводить больше ключевых слов, потому что они всегда ломают некоторый существующий код, который использовал это как идентификатор, когда это не было ключевое слово.

Позже, typename стало ключевым словом по другим причинам, и, поскольку оно гораздо лучше подходит, теперь его можно использовать в этом месте: template <typename Foo>. Однако с миллиардами строк кода, использующими class в этом месте, он должен оставаться действительным для этой цели. Так что теперь оба разрешены.

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

3 голосов
/ 26 марта 2010

Поскольку ключевое слово для параметров шаблона - class или typename. Это не ограничивает параметр Foo классом - он может быть любого типа.

3 голосов
/ 26 марта 2010

Вы можете создать экземпляр шаблона, используя структуру; однако синтаксис объявления типа шаблона позволяет отображать только ключевые слова «class» или «typename» там, где вы пытаетесь использовать ключевое слово «struct».

Я должен добавить, что вы также можете использовать определенный тип (например, int), если вы хотите создать экземпляр шаблона на основе константы времени компиляции или на основе объекта с внешней связью ... но это отчасти в сторону.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...