Конструктор по умолчанию не будет компилироваться внутри класса шаблона, если включены скобки (g ++ 4.6.1) - PullRequest
1 голос
/ 19 марта 2012

Не удалось найти в Google никакой информации об этом, в следующем примере:

    #include <iostream>

    class Default
    {
    public:
      void Print()
      {
        std::cout << "This is a message\n";
      }
    };

    template <class C = Default>
    class Template
    {
    public:
      static void Test()
      {
        Default oDefault();
      }
    };

    int main()
    {
      return 0;
    }

код не компилируется с ошибкой:

В статической функции-члене static void Template :: Test (): 19:22: ошибка: аргументы шаблона по умолчанию нельзя использовать в шаблонах функций без -std = c ++ 0x или -std = gnu ++ 0x

Проблема в том, что ему не нравятся квадратные скобки в этой строке, и я не понимаю, почему. Если я уберу скобки, код скомпилируется просто отлично. Кроме того, если я удаляю объявление шаблона (строка 13), он также прекрасно компилируется. Это ошибка или есть какое-то правило о такой ситуации?

Я использую g ++ 4.6.1 (gcc версии 4.6.1 (Ubuntu / Linaro 4.6.1-9ubuntu3))

Ответы [ 2 ]

2 голосов
/ 19 марта 2012

Измените его на:

 Default oDefault = Default();  // Version 1

Хотя вы можете использовать:

 Default oDefault;              // Version 2

Это имеет немного другое значение.

  • Версия 1: инициализирует нулями элементы POD (в некоторых ситуациях).
  • Версия 2. Вызывает неинициализацию членов POD (в некоторых ситуациях).

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

Вы должны предпочесть нулевую инициализацию по умолчанию (в целом), как если бы класс (или любой тип членов) не имел определяемого пользователем конструктора (как по умолчанию), тогда разница в том, что инициализация по умолчанию оставляет члены POD неопределенными, а ноль -инициализированные листья POD инициализируются нулями. Теперь вы можете подумать, что в моем классе нет участников, так что это не имеет значения. Но что произойдет, если вы измените класс, вы собираетесь найти все экземпляры и обновить их; Лучше всего использовать первую версию и позволить компилятору делать правильные вещи.

Подробности о том, как сногсшибательно см .:

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

1 голос
/ 19 марта 2012
Default oDefault();

Компилятор видит это как объявление функции, а не как создание объекта.
Он объявляет функцию oDefault(), которая не принимает параметров и возвращает объект Default.

Измените его на:

Default oDefault;
...