1

The snippet below was obtained from DR 2083 by Hubert Tong.

extern int globx;
int main() {
    const int &x = globx;
    struct A {
        const int *foo() { return &x; }
    } a;
    return *a.foo();
}

Then the author writes:

x satisfies the requirements for appearing in a constant expression, but applying the lvalue-to-rvalue converstion to x does not yield a constant expression.

Why applying the lvalue-to-rvalue conversion to x does not yield a constant-expression?

João Afonso
  • 1,934
  • 13
  • 19
  • 1
    The value of `globx`, and its memory address, are both not known until runtime. I see no "constant expression" or "lvalue-to-rvalue conversion" in this code – Remy Lebeau Mar 30 '21 at 18:36
  • @RemyLebeau I fail to see your point. `x` does satisfy requirements for appearing in constant expression, so what are you trying to say? – SergeyA Mar 30 '21 at 18:40

1 Answers1

4

Applying the lvalue-to-rvalue conversion to x reads the value of the mutable global variable globx, which makes it not a constant expression as the value of globx is subject to change (and, even if it were const, there would be the issue of its value not being known at compile time). Of course, this is not surprising: no one would expect int{x} to be a constant expression. The DR points out that this fact should, nonetheless, not cause the odr-use of x and thus the code should be well-formed: since x has constant initialization, the compiler can just translate &x into &globx.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • When you say "Applying the l-to-r conversion to `x` reads the value of the mutable global variable `globx`", I don't agree with that. Applying the l-to-r conversion to `x` reads the value of the variable `x`, not `globx`. – João Afonso Mar 30 '21 at 18:45
  • @JoãoAfonso I'm sorry, but that makes no sense whatsoever. The standard quite clearly says "the object indicated by the glvalue is read". References are not objects. – Brian Bi Mar 30 '21 at 18:55
  • I think you're right because `x` is a reference, thus an l-to-r conversion applied to `x` reads the value of `globx`. – João Afonso Mar 30 '21 at 18:56
  • What do you mean by "no one would expect `int(x)` to be a constant expression"? – João Afonso Mar 30 '21 at 18:59
  • @JoãoAfonso I think it's clear to everyone that the value of `int{x}` is not a compile-time constant. Applying the lvalue-to-rvalue conversion to `x` is basically computing `int{x}`. – Brian Bi Mar 30 '21 at 19:01
  • I'm sorry. I'm not familiar with this expression `int{x}`. – João Afonso Mar 30 '21 at 19:02
  • @JoãoAfonso please see [expr.type.conv] (C++20 §7.6.1.3) for explanation – Brian Bi Mar 30 '21 at 19:03
  • Now I understand that int{x} is equivalent to int(x). Thanks. – João Afonso Mar 30 '21 at 19:06
  • There is still one thing that I'm missing: why applying the l-to-r conversion to `x` is basically computing `int{x}` ? – João Afonso Mar 30 '21 at 19:14
  • @JoãoAfonso In writing my answer, I assumed that the reader would be familiar with what `int{x}` does (to provide intuition for what happens during an lvalue-to-rvalue conversion). However, since you were not familiar with this syntax, I apologize for causing more confusion. Anyway, because `int{x}` also causes the value of `x` to be read, that's why it has the same effect as an lvalue-to-rvalue conversion. – Brian Bi Mar 30 '21 at 19:26