2

N4527 5.20[expr.const]p2

A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine (1.9), would evaluate one of the following expressions:

(2.7) — an lvalue-to-rvalue conversion (4.1) unless it is applied to

(2.7.1) — a non-volatile glvalue of integral or enumeration type that refers to a complete non-volatile const object with a preceding initialization, initialized with a constant expression, or

(2.7.2) — a non-volatile glvalue that refers to a subobject of a string literal (2.13.5), or

(2.7.3) — a non-volatile glvalue that refers to a non-volatile object defined with constexpr, or that refers to a non-mutable sub-object of such an object, or

(2.7.4) — a non-volatile glvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of e;

5.20[expr.const]p5

A constant expression is either a glvalue core constant expression whose value refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value is an object where, for that object and its subobjects:

— each non-static data member of reference type refers to an entity that is a permitted result of a constant expression, and

— if the object or subobject is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object (5.7), the address of a function, or a null pointer value.

An entity is a permitted result of a constant expression if it is an object with static storage duration that is either not a temporary object or is a temporary object whose value satisfies the above constraints, or it is a function.

void foo(){
    const int a = 1;//a has automatic storage duration
    int b[a]{};
}

In int b[a]{};, a is an id-expression, a is a lvalue core constant expression. Is a a constant expression?


This is a clarification of Is a glvalue integral constant expression a constant expression?

Community
  • 1
  • 1
stackcpp
  • 1,275
  • 7
  • 15

1 Answers1

4

a can be a prvalue core constant expression, but not a glvalue core constant expression, nor should that be possible. You already found the wording in the standard, so perhaps it's better to explain why the rules are what they are.

void foo(){
    const int a = 1;//a has automatic storage duration
    static constexpr const int &ra = a;// cannot possibly be valid
}

This cannot be valid because it would require the address of a to be known before foo gets called, before there is any a.

Your int b[a]{}; is fine, because it's using a as a prvalue core constant expression: it doesn't care where a is stored, it merely cares what value it has.

  • I think `a` is a lvalue core constant expression, but it can't be constant expression as lvalue core constant expression, after lvalue-to-rvalue conversion, there's a prvalue core constant expression, that can be constant expression. – stackcpp Jul 21 '15 at 11:41
  • Sorry, what are you trying to say? – underscore_d Jul 21 '15 at 11:45
  • @underscore_d I think `a` is a lvalue core constant expression. Because `a` has automatic storage duration, so `a` is not a constant expression. But after lvalue-to-rvalue conversion, there will be a constant expression. Reference binding has no lvalue-to-rvalue conversion. Am I right? @hvd – stackcpp Jul 21 '15 at 11:52
  • @stackcpp I'm pretty sure that means that `a` *isn't* a glvalue core constant expression. But your conclusions after that look right to me, so at worst, there's just an issue about terminology. –  Jul 21 '15 at 13:00
  • @hvd I think these are three kinds of experssion categorizations. An expression can be a glvalue or not. An expression can be a core constant expression or not. An expression can be a constant expression or not. `a` is an lvalue, `a` is a core constant expression, but `a` is not a constant expression because it has automatic storage duration. `a` is not a constant expression but it can used as array boundary, this is werid. So I ask this question. – stackcpp Jul 21 '15 at 13:18
  • How is that weird? It has been this way ever since C. `const` variables' values are known by the compiler and can be used in places that require known `const`ant values. _Addresses_ of automatic `const` variables cannot be known until runtime. I don't see how `constexpr` is relevant here - except that it proves the latter point for us. – underscore_d Jul 21 '15 at 13:32
  • @underscore_d See the definition of constant expression. `a` has automatic storage duration so it is **not** a **constant expression**. As you said "It has been this way ever since C", so it should be a constant expression. There must be misunderstanding somewhere, I am confused. – stackcpp Jul 21 '15 at 13:44
  • C does not have `constexpr`. When I said "since C", I was referring to the fact that compile-time `const` values can be used in conditions where `const` literals would be expected. Pointers/references cannot. I agree there must be a misunderstanding as I'm not sure what you're confused about. ;-) – underscore_d Jul 21 '15 at 14:32
  • @underscore_d Is `a` a constant expression? If it is, then it conflicts with the definition of constant expression because it has automatic storage duration. If it is not, then why it could be used as array boundary? This is what I am confused about. – stackcpp Jul 21 '15 at 14:39
  • Its `const` value can be deduced at compile time and hence is valid for sizing an array, regardless of whether it has been explicitly qualified with `constexpr`. The compiler knows that `a` will always evaluate to 1, even if its _address_ is not available until runtime. Have a read of this: http://stackoverflow.com/questions/14116003/difference-between-constexpr-and-const – underscore_d Jul 21 '15 at 14:48
  • @underscore_d I am reading N4527 5.20[expr.const], and for an expression, I want to know if it is an constant expression. For `a` has automatic storage duration, I have the questions above. This is not about const and constexpr. – stackcpp Jul 21 '15 at 14:59
  • 1
    @stackcpp "I think these are three kinds of experssion categorizations. [...]" -- Okay. Suppose we make the implicit lvalue-to-rvalue conversion explicit and call it `$`. Then `a` is an lvalue and it's not a constant expression. But `$a` is a prvalue and it's a core constant expression. But in regular C++, where the `$` is invisible, you can't tell from just `a` whether the lvalue-to-rvalue conversion will have been applied, and because of that, you can't answer whether it's a core constant expression. You can only say that if it's used as an lvalue, it's not. If it's used as a prvalue, it is. –  Jul 21 '15 at 17:11
  • @hvd 'a' is an lvalue regardless where it occurs. 3.10 Lvalues and rvalues "_An lvalue designates a function or an object_". In context of `int &b = a;` there is no lvalue-to-rvalue conversion, 5.20p2 "_A conditional-expression e is a core constant expression_", so `a` is a core constant expression, `a` is not a constant expression because it has automatic storage duration. In context of `int b[a]{}`, there is a lvalue-to-rvalue conversion and according to 5.20p2.7 `a` is a core constant expression. `a` is not a constant expression because it has automatic storage duration. But `$a` is. – stackcpp Jul 21 '15 at 22:15