Переменная non-constexpr, иногда используемая в контексте constexpr? - PullRequest
2 голосов
/ 26 января 2020

Взгляните на следующий пример кода:

template<bool val>
struct test {
    static const int value_a = val;
    const int value_b = val;
    constexpr int get_value_a() const noexcept { return value_a; }
    constexpr int get_value_b() const noexcept { return value_b; }
};


int main(int argc, char** argv) {
    auto t = test<true>{};
    static_assert(t.value_a);
    // static_assert(t.value_b);
    static_assert(t.get_value_a());
    // static_assert(t.get_value_b());
}

И g cc, и clang согласны, что это должно скомпилироваться, но включение любого закомментированного утверждения stati c делает его недействительным. Например, g cc выдаст следующие сообщения об ошибках:

error: непостоянное условие для stati c assertion

error: значение 't' равно не может использоваться в константном выражении

примечание: 't' не было объявлено 'constexpr'

Это имеет для меня абсолютный смысл и является именно тем, что я бы подумал. Но я действительно не знаю, почему две другие команды c в первую очередь утверждают, что они компилируются. Какой соответствующий абзац из стандарта позволяет это сделать?

В частности, как это формализовано? Есть ли четко определенная разница между просто использованием переменной и фактическим доступом к ее значению во время выполнения (что тогда будет единственной запрещенной вещью в контексте constexpr)?

Ответы [ 3 ]

1 голос
/ 26 января 2020

В частности, как это формализовано?

http://eel.is/c++draft/expr.const#4 .1

Выражение e является основной константой Выражение, если вычисление e, следуя правилам абстрактной машины ([intro.execution]), не оценило бы одно из следующего:

this ([expr.prim.this]), кроме функция constexpr ([dcl.constexpr]), которая оценивается как часть e;

Доступ к не * stati c членам оценивает указатель this. Доступ к участнику stati c отсутствует.

1 голос
/ 26 января 2020

Это просто правила. До того, как constexpr, переменные const, инициализированные с помощью константных выражений, могли использоваться как сами константы (также для некоторой совместимости с C)

Из стандарта [expr.const]/3:

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

Это не будет распространяться на const auto t = test<true>{}, потому что test<true> не является целочисленным типом (вам нужно иметь constexpr auto t = test<true>{}, как ожидается, следуя правилам остальной части этого параграфа) * ​​1017 *

0 голосов
/ 26 января 2020

Адрес value_b не может быть оценен во время компиляции.

Только данные c могут быть объявлены как constexpr.

Связанные: Почему можно не являются ли c членами данных be constexpr?

...