C++ integral constant expression definition

Viewed 690

In the current C++ standard there is the following paragraph (expr.const#5) (emphasis mine):

An integral constant expression is an expression of integral or unscoped enumeration type, implicitly converted to a prvalue, where the converted expression is a core constant expression. [ Note: Such expressions may be used as bit-field lengths, as enumerator initializers if the underlying type is not fixed ([dcl.enum]), and as alignments. — end note ]

I have two questions regarding this definition:

  1. Does the phrase "implicitly converted to a prvalue" mean that for an expression to be considered an "integral constant expression" it must appear in a context that forces it to be implicitly converted to a prvalue?

  2. What does "the converted expression" refer to? I know that this question is addressed in Clarification of converted constant expression definition. The answer given there is that "the converted expression" is t, after the following initialization: T t = expr;. However, I do not see how evaluating that expression (t) would match any of the rules given in [expr.const#4] (paragraph describing required conditions for an expression to be considered a core constant expression) which would make it unqualified to be a core constant expression.

Thank you.

2 Answers

The statement that an integral constant expression is implicitly converted to a prvalue means that the lvalue-to-rvalue conversion is applied to any expression used as an integral constant expression. In the one case where an expression might be an integral constant expression—initializing a non-local object of const-qualified integer type that might be usable in constant expressions—the initializer is a prvalue anyway, so no change of interpretation can occur.

Beyond that, both of your questions have the same answer: whatever conversions are necessary to bring the expression (as written) to a prvalue integral type must also be allowed in a core constant expression (see, for example, /4.7 just before your citation and /6 just after it). The “converted expression” comprises the conversion in the T t=e; interpretation, not just the id-expression t (which would, for instance, always be an lvalue).

I looked at clang's source code, specifically, at the function "CheckConvertedConstantExpression" inside "SemaOverload.cpp". The operations performed there are as follows:

  1. find the required implicit conversion sequence
  2. check to see if only conversions listed in http://eel.is/c++draft/expr.const#7 are used
  3. perform the implicit conversion (at this step I believe a new expression is created, e.g. if the original expression is f() which is of class type A with a user-defined conversion function to int, and the context requires an int, then the new expression should be f().operator int())
  4. check if any narrowing conversions are required
  5. evaluate the expression generated at step 3 (which implicitly checks if it is a constant expression)

So I believe that, as stated in @Davis Herring's answer, the term "converted expression" means a new expression whose evaluation comprises both the evaluation of the original expression, as written in the program, and the evaluation of any required conversion.

Related