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

Чтение шаблонов C++: полное руководство

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

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

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

Пример:

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"

7 ответов

Решение

Это означает, что вы не можете сделать что-то вроде следующего

  void foo()
  {
       template <typename T> //Error
       T something;
  }

Объявления шаблонов разрешены только в глобальном пространстве, пространстве имен или области видимости.:)

В чем причина этого?

Это не разрешено, потому что Стандарт говорит так.

ISO C++ - 98 (раздел 14.2)

Объявление шаблона может появляться только как объявление пространства имен или области видимости.

Имеет ли это смысл?

Проблема, вероятно, связана с историческим способом реализации шаблонов: методы ранней реализации (а некоторые до сих пор используются сегодня) требуют, чтобы все символы в шаблоне имели внешнюю связь. (Реализация выполняется путем создания эквивалентного кода в отдельном файле.) Имена, определенные внутри функции, никогда не имеют связи и не могут быть использованы вне области, в которой они были определены.

Ответ "потому что стандарт так говорит", конечно, правильный, но давайте рассмотрим общие лямбды.

В C++14 и C++17 универсальные лямбды являются единственным способом написания шаблонного кода, о котором я знаю:

    auto lambda = [](auto x) { };
    lambda.operator()<int>(0);

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

Это будет проще в C++20, хотя. С помощью списка параметров шаблона в общих лямбдах вы сможете написать код, подобный этому:

    auto size = []<class T>() { return sizeof(T); };
    static_assert(4 == size.operator()<int>());

GCC уже поддерживает этот синтаксис.

Короткий ответ на вопрос, почему это так, заключается в том, что так хотели парни, написавшие компиляторы и стандарты c/ C++. Шаблоны внутри функций должны были считаться слишком хаотичными и / или трудными для понимания или анализа, поэтому они запрещали это.

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

Я предполагаю, что это трудно реализовать, поэтому это запрещено. Написание шаблонов классов вне функций - приемлемое решение с другой стороны.

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

Другие вопросы по тегам