Могу ли я использовать статический константный float в заголовке с инициализацией значения - PullRequest
0 голосов
/ 30 мая 2018

У меня есть этот вопрос, который меня беспокоит.

Почему не могу у меня подобный код в моем файле .hpp.

class H {
  private:
    static const int i =5;
    static const float f = 1.0;
    static const string s = "string";
}

Только так могут быть объявлены и инициализированы только int, bool, enum, constexpr и т. Д.

Мои вопросы:

  1. Почему строки и другие сложные типы данных нуждаются в правильной инициализации в cpp?Они постоянны.

  2. Почему у нас разное поведение для чисел с плавающей запятой и целых?мое предположение: gcc не поддерживает это, но может быть легко поддержано, если мы используем constexpr.

1 Ответ

0 голосов
/ 30 мая 2018

Это потому, что стандарт так говорит.

Обычно правило определения out-of-line применяется к static const элементам:

Объявлениеэлемента данных static в его определении класса является , а не определением.

Единственное исключение состоит в том, что, поскольку C ++ 11 целочисленные и enum static const типы могут бытьинициализируется in-line.

См. [class.static.data] / 3 (выделено мной):

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

Как упомянул Бьярне :

Итакпочему существуют эти неудобные ограничения?Класс обычно объявляется в файле заголовка, а файл заголовка обычно включается во многие единицы перевода.Однако, чтобы избежать сложных правил компоновщика, C ++ требует, чтобы у каждого объекта было уникальное определение.Это правило было бы нарушено, если бы C ++ допускал в классе определение сущностей, которые должны были храниться в памяти как объекты.

Рациональным могло бы быть то, что целочисленные типы становятся константами времени компиляции, хотя я склоненне согласиться, потому что правило единого адреса в единицах компиляции все еще применяется, что означает, что компилятор должен по-прежнему испускать элементы static const со слабой связью и заставить компоновщик сворачивать их, так же, как это происходит с множественно определенными шаблонами.В этот момент ограничение на целочисленные типы становится спорным, поскольку одно и то же сворачивание может быть применено к любому типу.Фактически, C ++ 17 «исправляет» это с помощью inline членов:

class H {
private:
    inline static const int i = 5;
    inline static const float f = 1.0;
    inline static const string s = "string";
};
...