Неинициализированный const

Это компилируется отлично с помощью текущего компилятора MSVC:

struct Foo
{
} const foo;

Однако он не скомпилируется с текущим компилятором g++:

error: uninitialized const 'foo' [-fpermissive]
note: 'const struct Foo' has no user-provided default constructor

Если я сам создаю конструктор по умолчанию, он работает:

struct Foo
{
    Foo() {}
} const foo;

Является ли это еще одним случаем, когда MSVC является слишком разрешимым или слишком строгим?

Ответы

Ответ 1

Стандарт С++ 03:

8.5 [dcl.init] пункт 9

Если для объекта не задан инициализатор, а объект имеет (возможно, cv-квалифицированный) тип класса не-POD (или его массив), объект должен быть инициализирован по умолчанию; если объект имеет тип const-type, базовый тип класса должен иметь объявленный пользователем конструктор по умолчанию.

Из вышесказанного ошибка в gcc представляется совершенно корректной.

Ответ 2

[2003: 8.5/9]: Если для объекта не задан инициализатор, а объект имеет (возможно, cv-квалифицированный) тип класса не-POD (или массив), объект должен быть инициализирован по умолчанию; если объект имеет const-qual type, тип базового класса должен иметь объявленный пользователем конструктор по умолчанию. В противном случае, если инициализатор не установлен для объекта, не являющегося объектом, объекта и его подобъектов, если любой, имеют неопределенное начальное значение; , если объект или любой из его подобъекты имеют const-квалифицированный тип, программа плохо сформирована.

и

[n3290: 8.5/11]: Если для объекта не задан инициализатор, объект инициализируется по умолчанию:, если инициализация отсутствует выполненный объект с автоматическим или динамическим временем хранения неопределенное значение. [Примечание: объекты со статическими или потоковыми хранилищами длительность нулевой инициализации, см. 3.6.2._ -end note_]

[n3290: 8.5/6]: По умолчанию инициализировать объект типа T означает:

  • , если T является (возможно, cv-qualit) типом класса (раздел 9), вызывается конструктор по умолчанию для T (и инициализация плохо сформирована, если T не имеет доступного конструктора по умолчанию)
  • if T - тип массива, каждый элемент инициализируется по умолчанию;
  • в противном случае инициализация не выполняется.

Если программа вызывает инициализацию по умолчанию объекта типа const-type T, T должен быть типом класса с предоставленным пользователем конструктором по умолчанию.

Итак, MSVC здесь более разрешительный, чем оба стандарта.

Ответ 3

Я не знаю точной формулировки стандарта, но ошибка в g++ кажется более разумной, чем возможность ничего не говорить. Рассмотрим это:

struct X {
   int value;
};
const X constant; // constant.value is undefined

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