int a=1, is a || 1 a constant expression?

a is not constant expression(see standard quote below) and therefore:

a || 1 

Is not a constant expression either, although we know the expression has to evaluate to true the standard requires left to right evaluation here and I see no exceptions that would allow the compiler to skip the lvalue-to-rvalue conversion of a.

but:

const int a = 1;

Could be used in a constant expression because it fall under the exception from 5.20p2 (emphasis mine):

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

  • 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
  • a non-volatile glvalue that refers to a subobject of a string literal (2.13.5), or
  • 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
  • a non-volatile glvalue of literal type that refers to a non-volatile object whose lifetime began
    within the evaluation of e

This rule is also why the original case is not a constant expression since none of the exception apply.

Perhaps gcc is allowing this:

int b[a || 1]{};

as a variable length array as an extension, although it should provide a warning using -pedantic. Although that would not explain the static_assert case, they could be constant folding it but I don’t think the as-if rule would allow it to be considered a constant expression.

Update, possible gcc extension

From this bug report RHS of logical operators may render LHS unevaluated in constant-expression this looks like a possible gcc extension:

This compiles without incident, despite using a non-constant object in
a constant-expression:

int i;
static_assert( i || true, "" );
static_assert( ! ( i && false ), "" );

It appears to be assuming that || and && are commutative, but
short-circuiting only works in one direction.

and the final comment says:

I think this is a purposeful language extension, which could use a switch to disable. It would be nice if static_assert were always strict.

This seems like a non-conforming extension that should trigger a warning when using the -pedantic flag similar in vain to issue in Is it a conforming compiler extension to treat non-constexpr standard library functions as constexpr?.

C++11/C++14 Quote

Section 5.20 is section 5.19 in C++14 and C++11, the relevant quote from the draft C++14 standard is:

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

  • a non-volatile glvalue of integral or enumeration type that refers to a non-volatile const object with
    a preceding initialization, initialized with a constant expression [ Note: a string literal (2.14.5)
    corresponds to an array of such objects. —end note ], or

  • 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

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

and for the draft C++11 standard is:

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

  • a glvalue of integral or enumeration type that refers to a non-volatile const object with a preceding
    initialization, initialized with a constant expression, or

  • a glvalue of literal type that refers to a non-volatile object defined with constexpr, or that refers
    to a sub-object of such an object, or

  • a glvalue of literal type that refers to a non-volatile temporary object whose lifetime has not
    ended, initialized with a constant expression;

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)