Приведенный ниже фрагмент был получен из DR 2083 Хьюбертом Тонгом.
extern int globx;
int main() {
const int &x = globx;
struct A {
const int *foo() { return &x; }
} a;
return *a.foo();
}
Далее автор пишет:
xsatisfies the requirements for appearing in a constant expression, but applying the lvalue-to-rvalue converstion toxdoes not yield a constant expression.
Почему применение преобразования lvalue-to-rvalue к x не дает константного выражения?
@RemyLebeau Я не понимаю твоей точки зрения. x действительно удовлетворяет требованиям присутствия в постоянном выражении, так что вы пытаетесь сказать?





Применение преобразования lvalue-to-rvalue к x считывает значение изменяемой глобальной переменной globx, что делает его не постоянным выражением, поскольку значение globx может изменяться (и даже если бы это был const, возникла бы проблема его значение не известно во время компиляции). Конечно, это неудивительно: никто не ожидал, что int{x} будет постоянным выражением. DR указывает, что этот факт, тем не менее, не должен вызывать odr-использование x, и, следовательно, код должен быть правильно сформирован: поскольку x имеет постоянную инициализацию, компилятор может просто транслировать &x в &globx.
Когда вы говорите: «Применение преобразования l-to-r к x приводит к считыванию значения изменяемой глобальной переменной globx», я с этим не согласен. Применение преобразования l-to-r к x считывает значение переменной x, а не globx.
@ JoãoAfonso Мне очень жаль, но в этом нет никакого смысла. В стандарте довольно четко сказано: «объект, указанный в glvalue, читается». Ссылки не являются объектами.
Я думаю, вы правы, потому что x является эталоном, поэтому преобразование l-to-r, примененное к x, считывает значение globx.
Что вы имеете в виду, говоря «никто не ожидал, что int(x) будет постоянным выражением»?
@ JoãoAfonso Я думаю, что всем ясно, что значение int{x} не является константой времени компиляции. Применение преобразования lvalue-to-rvalue к x в основном вычисляет int{x}.
Мне жаль. Я не знаком с этим выражением int{x}.
@ JoãoAfonso, пожалуйста, см. [Expr.type.conv] (C++ 20 §7.6.1.3) для объяснения
Теперь я понимаю, что int {x} эквивалентен int (x). Спасибо.
Есть еще одна вещь, которую мне не хватает: почему применение преобразования l-to-r к x в основном означает вычисление int{x}?
@ JoãoAfonso При написании своего ответа я предполагал, что читатель будет знаком с тем, что делает int{x} (чтобы интуитивно понять, что происходит во время преобразования lvalue-to-rvalue). Однако, поскольку вы не были знакомы с этим синтаксисом, прошу прощения за то, что вызвал еще больше путаницы. В любом случае, поскольку int{x} также вызывает чтение значения x, поэтому он имеет тот же эффект, что и преобразование lvalue-to-rvalue.
Теперь все ясно. Спасибо..
Значение
globxи его адрес памяти неизвестны до времени выполнения. Я не вижу в этом коде "постоянного выражения" или "преобразования lvalue-to-rvalue"