Псевдоним шаблона
Согласно http://en.cppreference.com/w/cpp/language/type_alias, псевдонимы являются объявлениями на уровне блоков. В псевдонимах шаблонов ничего особенного не говорится, поэтому следует помнить, что псевдонимы шаблонов также являются объявлениями на уровне блоков.
Однако невозможно использовать псевдонимы шаблонов на уровне блоков. Ошибки различаются в зависимости от компилятора - в то время как g++ дает осмысленное сообщение о том, что шаблоны не допускаются в области видимости блока, clang полностью загадочен. (пример: http://coliru.stacked-crooked.com/a/0f0862dad6f3da61).
Вопросы, которые у меня есть до сих пор:
- Не указывает ли cppreference, что псевдонимы шаблона нельзя использовать в области видимости блока? (Или мне нужно пройти курс чтения?)
- Правильны ли компиляторы в запрете псевдонимов шаблонов на уровне блоков (функция, которую я нахожу очень интересной для моих конкретных привычек кодирования)
- Если ответ на второй вопрос - "Да", что может быть обоснованием для этого? Почему компилятор отказывает мне в этом чистом синтаксисе?
2 ответа
Шаблон псевдонима - [temp.alias]
Объявление шаблона, в котором объявление является объявлением псевдонима (раздел 7), объявляет идентификатор как шаблон псевдонима. Шаблон псевдонима - это имя для семейства типов. Имя шаблона псевдонима - это имя шаблона.
И если мы посмотрим на 14,2 [темп], мы имеем
Объявление шаблона может появляться только как область видимости пространства имен или декларация области класса. В объявлении шаблона функции последний компонент идентификатора объявления не должен быть идентификатором шаблона.
Так что да, cppreference отключен, говоря, что он может быть объявлен в области видимости блока, и ваши компиляторы верны. Если вы нажмете на ссылку объявлений блока, то вы попадете в список объявлений, в котором есть объявление шаблона, и там есть
объявление класса (включая структуру и объединение), класса-члена или типа перечисления члена, функции или функции-члена, статического члена данных в области имен, переменной или статического члена данных в области класса (начиная с C++14) или шаблон псевдонима (начиная с C++11). Он также может определять специализацию шаблона.
Что касается того, почему стандарт говорит, что шаблоны могут быть объявлены только в области имен или в области классов, мне нравится ответ James Kanze
Проблема, вероятно, связана с историческим способом реализации шаблонов: методы ранней реализации (а некоторые до сих пор используются сегодня) требуют, чтобы все символы в шаблоне имели внешнюю связь. (Реализация выполняется путем создания эквивалентного кода в отдельном файле.) Имена, определенные внутри функции, никогда не имеют связи и не могут быть переданы за пределы области, в которой они были определены.
Компиляторы ведут себя правильно.
Раздел 14 стандарта C++14:
Объявление шаблона может появляться только как область видимости пространства имен или декларация области класса.