2015-06-09 3 views
12

В C++ 11 и С ++ 14, для чего необходимо constexpr в следующем фрагменте:Постоянного выражения инициализатора для статического члена класса типа двойного

class Foo { 
    static constexpr double X = 0.75; 
}; 

в то время как этот производит ошибку компиляции:

class Foo { 
    static const double X = 0.75; 
}; 

и (более удивительно) компилируется без ошибок?

class Foo { 
    static const double X; 
}; 

const double Foo::X = 0.75; 
+2

В основном совместимость с C++ 03, [здесь сводка] (http://stackoverflow.com/a/28846608/1708801) –

+0

Один синтаксис для констант времени компиляции, отличный от синтаксиса для создания 'static' переменная-член, которая является 'const' с значением по умолчанию (и, следовательно, сингулярным). Возможно, часть логики здесь заключается в том, что const может быть нарушен, и если вы говорите, что хотите иметь возможность принять адрес вещи, вы, возможно, до таких махинаций. – kfsone

+0

@Stefano Sanfilippo: Почему последний пример описывается как «более удивительный»? На самом деле это базовое поведение, существующее на языке с начала времен. – AnT

ответ

8

В C++ 03 мы были только позволили обеспечить в классе инициализаторе для статических переменных членов сопзИте интеграл перечислимых типов в C++ 11, мы могли бы инициализировать статический элемент буквального типа в классе с использованием constexpr. Это ограничение хранилась в C++ 11 для константных переменных в основном для совместимости будет C++ 03, мы можем увидеть это из closed issue 1826: const floating-point in constant expressions, который говорит:

A const integer initialized with a constant can be used in constant expressions, but a const floating point variable initialized with a constant cannot. This was intentional, to be compatible with C++03 while encouraging the consistent use of constexpr. Some people have found this distinction to be surprising, however.

РГС закончилась закрытием этого запроса, как не дефект (NAD), в основном говорят:

that programmers desiring floating point values to participate in constant expressions should use constexpr instead of const.

для справки N1804 ближайший проект стандарта для C++ 03 общедоступными в разделе 9.4.2[class.static.data] говорит:

If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19). In that case, the member can appear in integral constant expressions. The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer.

и проект C++ 11 стандартный раздел 9.4.2[class.static.data] говорит:

If a non-volatile const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment expression is a constant expression (5.19). A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [...]

это в значительной степени то же самое в стандарте в проекте C++ 14.

0

«определения» статического константы класса «in» - это фактически декларации. Когда переменная определена, компилятор выделяет память для этой переменной, но здесь это не так, т. Е. С учетом того, что адрес этих статических конструкций в классе не сформирован, NDR.

Эти вещи должны быть обработаны в коде, но это не так просто сделать с типами с плавающей точкой, поэтому это недопустимо.

Определяя ваши постоянные переменные const вне класса, вы сигнализируете компилятору, что это реальное определение - реальный экземпляр с памятью.

+0

Это на самом деле плохо сформированный NDR, а не UB. – Brian

+0

* «но это не так просто сделать с типами с плавающей точкой, поэтому это не разрешено». Возможно, это было в случае с C++ 98/03, но C++ 11 представил 'constexpr', что позволяет' struct X {constexpr static double d = 5.0; }; ' – dyp

+0

@dyp Вы говорите, что в код также обрабатываются типы с плавающей запятой ?!Я думал, что это «реальное определение», т. Е. Constexpr double хранится где-то в памяти. –

Смежные вопросы