stella
stella

Reputation: 2596

Understanding constant expression

I'm trying to understand the constant expression concept (from c++reference):

struct S {
    static const int c;
};
const int d = 10 * S::c; // not a constant expression: S::c has no preceding
                         // initializer, this initialization happens after const
const int S::c = 5;      // constant initialization, guaranteed to happen first

Why isn't the S::c a constant expression untill we define it. It was declared as a static const data member though...

Upvotes: 4

Views: 162

Answers (3)

o11c
o11c

Reputation: 16076

Quoting relevant part of the C++11 standard (draft N3337), section 5.19, paragraph 2:

A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression (3.2), but subexpressions of logical AND (5.14), logical OR (5.15), and conditional (5.16) operations that are not evaluated are not considered [ Note: An overloaded operator invokes a function. — end note ]:

  • 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

There is no preceding initialization of S::c in your definition of d.

Edit: why this applies:

  • 5.1.1/8: S::c is an lvalue.
  • 3.10/1: a glvalue is an lvalue or xvalue.
  • 5/8: specifies that lvalue-to-rvalue conversion happens whenever an operator that expects a prvalue is used.
  • Proving that multiplication expects a prvalue is hurting my head. It is implied in many places, but I haven't found anywhere it is said explicitly.

Upvotes: 4

ross
ross

Reputation: 526

Constant initialization is performed before other initialization in the C++ compiling process. In the example, the constant initialization of d is guaranteed to occur before the constant initialization of S::c. A constant expression must consist exclusively of constant values. When d is initialized, S::c is known to be a constant value, so the expression is not considered constant.

Upvotes: 1

dlask
dlask

Reputation: 8982

In this sequence …

constexpr int d = 10 * S::c;
const int S::c = 5;

… the value of S::c is not known yet when the d value is compiled. But try to swap these lines:

const int S::c = 5;
constexpr int d = 10 * S::c;

Upvotes: 2

Related Questions