Подтвердить что ты не робот

Почему шаблоны не могут быть объявлены в функции?

Чтение Шаблоны С++: Полное руководство, и он говорит

Обратите внимание, что шаблоны не могут быть объявлены в функции

Он не дает объяснений и/или перекрестных ссылок на любую другую главу книги или внешнего ресурса.

Помог ли кто-нибудь объяснить это. Вероятно, это объясняется позже в книге, но еще нет. Если объяснено ранее, я, должно быть, пропустил его.

Пример:

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"
4b9b3361

Ответ 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

Что именно будет использоваться? Таким образом, вы можете объявлять переменные шаблона, которые вы можете использовать только внутри функции? Это действительно полезно?