Подтвердить что ты не робот

Значение переменной const является или не может использоваться в постоянном выражении, в зависимости от типа переменной

Следующий код в порядке:

constexpr double square_cstxpr(double x) { return x * x; }

int main() {
    const int test = 5;
    constexpr double result = square_cstxpr((double)test);
}

Однако, если тип test изменен с const int на const double, g++ дает следующую ошибку: the value of 'test' is not usable in a constant expression.

Смотрите код и вывод g++ здесь: http://coliru.stacked-crooked.com/a/2fe9b176c2b23798

Может ли кто-нибудь объяснить это поведение?

4b9b3361

Ответ 1

Не <constexpr, но const переменные должны быть целочисленного или перечисляемого типа, чтобы они могли использоваться в постоянных выражениях. См. [expr.const]/2:

преобразование lvalue-rvalue, если оно не применяется к

(2.7.1) нестабильное значение gl интегрального или перечисляемого типакоторый относится к полному нелетучивому объекту const с предшествующим инициализация, инициализированная постоянным выражением, или [..]

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

Ответ 2

Из константное выражение (Основные константные выражения):

10) Любое другое неявное преобразование lvalue-rvalue, если только именующий...

a) имеет интегральный или перечисляемый тип и относится к полной нелетучей const, который инициализируется постоянным выражением

Это означает, что здесь:

const int test1 = 5;
constexpr double result1 = square_cstxpr((double)test1);

test1 является константным выражением, square_cstxpr можно вызывать с test1 в качестве аргумента во время компиляции, и его результат может быть назначен переменной constexpr result.

С другой стороны, здесь:

const double test2 = 5;
constexpr double result2 = square_cstxpr((double)test2);

test2 не является постоянным выражением, поскольку он не является целым или перечисляемым типом. Следовательно, square_cstxpr нельзя вызывать во время компиляции с test2 в качестве аргумента.