2

[dcl.constexpr] p10 sentence 3 says:

In any constexpr variable declaration, the full-expression of the initialization shall be a constant expression

However, in this declaration:

constexpr int a = 10;
constexpr int b = a;

a is not a constant expression, as it is glvalue core constant expression, but not a permitted result of a constant expression because it does not have static storage duration, and is not a temporary object.

However, with the application of an lvalue-to-rvalue conversion, it will become a constant expression. So does that mean that the initializer does not need to be a constant expression, and only the final result after conversions has to be?

curiousguy
  • 8,038
  • 2
  • 40
  • 58
Krystian S
  • 1,586
  • 7
  • 23
  • It seems a defect in the standard that the value category of a full-expression is not defined. – xskxzr Aug 08 '19 at 02:41
  • _"It seems a defect in the standard that the value category of a full-expression is not defined."_ Seems to me incorrect. [const.expr#11](https://timsong-cpp.github.io/cppwp/n4868/expr.const#11) already gives it a value category which is either a glvalue or prvalue. I don't see any defect here. – mada Sep 29 '22 at 06:12

2 Answers2

3

In the link you quoted, see point 10:

A constant expression is either a glvalue core constant expression that refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value satisfies the following constraints:

Your question focused on "permitted result of a constant expression" under the glvalue branch; however in your example it is the other branch "prvalue core constant expression" that applies. This can apply because of [conv.lval]/1,

A glvalue of a non-function, non-array type T can be converted to a prvalue

I agree it is a bit confusing that by "prvalue core constant expression" here they include the case of the result of lvalue-to-rvalue conversion on glvalues that meet the criteria; whereas in some other places in the standard "prvalue" excludes that case.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • perhaps I am misinterpreting what a full-expression is, particularly when the wording says that conversions are "part of the full-expression". A full expression is an expression, so if a conversion is part of that expression, does that mean that the inner expression is effectively "nested" inside the conversion, so when the full-expression is evaluated, it's the nested expression with that conversion applied being the result? – Krystian S Aug 08 '19 at 03:10
  • @KrystianS I think the part about the "full-expression of the initialization" is saying that the initializer (after any conversions to it are applied) should be a constant expression – M.M Aug 08 '19 at 03:23
  • Ok, so would a good definition for full-expression be "a full-expression is the outermost expression or conversion that is evaluated when a statement is executed"? – Krystian S Aug 08 '19 at 03:40
  • Actually, no, it can't be, because a full-expression is not necessarily a single expression. – Krystian S Aug 08 '19 at 03:58
  • The standard defines *full-expression*, you can consult that – M.M Aug 08 '19 at 05:10
  • It does, but the intent is not clear. Obviously, it exists to define the order of execution, and the lifetime of temporaries, however the confusing thing is the way in which it is defined and use. It is stated that a full-expression "includes" conversions that are applied, but this is confusing because an expression is a singular thing. Addtionally, a full-expression can be made up of multiple disjoint expressions, such as the elements of an initializer, which is confusing since it is described as a singular expression. – Krystian S Aug 08 '19 at 10:53
1

The word "full-expression" is a defined term. Notably ([intro.execution]/5)

Conversions applied to the result of an expression in order to satisfy the requirements of the language construct in which the expression appears are also considered to be part of the full-expression.

So yes, since the requirement says "the full-expression of the initialization shall be a constant expression", it means only the full-expression (which includes the conversion), not anything else, is required to be a constant expression.

cpplearner
  • 13,776
  • 2
  • 47
  • 72
  • 1
    That's wasn't the question - rather what is the "initialization"? Obviously it includes the conversions, but does it include the initializer? The full expression of an initializer is itself, and any other conversions that are applied, but it is not clear if "initialization" includes the initializer expression itself. – Krystian S Aug 07 '19 at 10:13
  • @KrystianS The full-*expression* is just the one in the initializer. – L. F. Aug 07 '19 at 12:32
  • @L.F. Ok, but in the example I showed in the question `a` isn't a constant expression – Krystian S Aug 07 '19 at 19:58
  • @KrystianS `a` is definitely a constant expression. If a constexpr variable is not a constant expression, what can possibly be? – L. F. Aug 07 '19 at 23:47
  • @L.F. It definitely is not, until the lvalue-to-rvalue conversion is applied. – Krystian S Aug 08 '19 at 03:06
  • @KrystianS OK, admittedly I wasn't trying to be a competent language lawyer in the previous comment. My point is that you can expect that `constexpr int b = a;` is valid here, so double-check the standard. – L. F. Aug 08 '19 at 03:09
  • 1
    @L.F. I think the wording makes sense (however, initialization may be a typo for initializer) and what is the issue is how I am interpreting what a full expression is. Since conversions are considered part of a full expression, would that mean that the initializer is effectively "nested" inside of the conversion, so when the full-expression is evaluated, its result is the result of the enclosing conversion. – Krystian S Aug 08 '19 at 03:14