Почему шаблоны не могут быть объявлены в функции?
Чтение Шаблоны С++: Полное руководство, и он говорит
Обратите внимание, что шаблоны не могут быть объявлены в функции
Он не дает объяснений и/или перекрестных ссылок на любую другую главу книги или внешнего ресурса.
Помог ли кто-нибудь объяснить это. Вероятно, это объясняется позже в книге, но еще нет. Если объяснено ранее, я, должно быть, пропустил его.
Пример:
int main()
{
class DummyClass // This compiles ok
{
int object;
};
template <typename T> // compile error "expected primary-expression before "template""
class DummyTemplate
{
T object;
};
return 0;
}
Я тоже не понимаю сообщение об ошибке из gcc. В сообщении об ошибке говорится:
expected primary-expression before "template"
Ответы
Ответ 1
Это означает, что вы не можете сделать что-то вроде следующего
void foo()
{
template <typename T> //Error
T something;
}
Объявления шаблона разрешены только в глобальном пространстве имен, пространства имен или класса.:)
Каковы причины этого?
Это не разрешено, потому что это говорит стандарт.
ISO С++ - 98 (раздел 14.2)
Объявление шаблона может отображаться только как объявление пространства имен или класса.
Это имеет смысл?
Ответ 2
Проблема, вероятно, связана с историческим способом создания шаблонов: ранние методы внедрения (и некоторые из них все еще используются сегодня) требуют, чтобы все символы в шаблоне имели внешнюю связь. (Активация выполняется путем генерации эквивалентного кода в отдельном файле.) И имена, определенные внутри функции, никогда не имеют привязки и не могут быть переданы за пределы области, в которой они были определены.
Ответ 3
Короткий ответ на вопрос, почему это так, заключается в том, что так хотели ребята, которые писали компиляторы и стандарты c/С++. Шаблоны внутри функций должны были считаться слишком хаотичными и/или трудными для понимания или анализа, поэтому они запретили его.
Ответ 4
Ответ "потому что стандарт так говорит", конечно, правильный, но давайте рассмотрим общие лямбды.
В С++ 14 и С++ 17 универсальные лямбды являются единственным способом написания шаблонного кода, о котором я знаю:
auto lambda = [](auto x) { };
lambda.operator()<int>(0);
Технически, вы можете написать любой код шаблона именно с этим. Хотя вам придется много работать, чтобы обойти различные ограничения этого подхода.
Это будет проще в С++ 20, хотя. С помощью списка параметров шаблона в общих лямбдах вы сможете написать код, подобный следующему:
auto size = []<class T>() { return sizeof(T); };
static_assert(4 == size.operator()<int>());
GCC уже поддерживает этот синтаксис.
Ответ 5
Единственный раз, когда это было бы полезно, было бы, если бы вы создали несколько экземпляров шаблона с разными типами с одной функцией. Все равно перемещайте свои частные классы из своих функций. Если это начинает загромождать ваши классы, они слишком велики и нуждаются в рефакторинге.
Ответ 6
Я предполагаю, что это трудно реализовать, поэтому это не разрешено (в стандарте С++ 03). Написание шаблонов классов вне функций - приемлемое решение с другой стороны.
Ответ 7
Что именно будет использоваться? Таким образом, вы можете объявлять переменные шаблона, которые вы можете использовать только внутри функции? Это действительно полезно?