ABu
ABu

Reputation: 12279

Taking the address of a literal, not a `constexpr`

Strictly according to the rules of C++14, at least the ones given by cppreference.com, isn't the line (1) a constant expression?

constexpr const int* addr(const int& ir) { return &ir; }
constexpr const int* tp = addr(5); // (1)

It's true that is not an address constant expression, because &ir isn't the address of a static object (&ir is the address of a temporary in this context, which cannot be known in compilation-time).

But it is a core constant expression because it doesn't violate any of the back-listed rules of core constant expression, which has no back-listed rules about getting the address of an object.

Upvotes: 3

Views: 279

Answers (1)

aschepler
aschepler

Reputation: 72401

No, addr(5) is not a constant expression, and therefore the posted code is ill-formed. Yes, you are correct that addr(5) is a core constant expression.

I can see why you might think from the cppreference page alone that core constant expressions, integral constant expressions, converted constant expressions, literal constant expressions, reference constant expressions, and address constant expressions are all types of constant expression. But the true definition is given in C++14 [expr.const]/4:

A constant expression is either a glvalue core constant expression whose value refers to an object with static storage duration or to a function, 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 object with static storage duration or to a function, 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, the address of a function, or a null pointer value.

Being a "core constant expression" does not have many direct implications; it's merely a term used to help define "integral constant expression", "converted constant expression of type T", and "constant expression". And "constant expression" actually describes a subset of the expressions described by "core constant expression", not a superset.

For example, and to be complete, the paragraph that makes the example ill-formed ([dcl.constexpr]/9) requires a constant expression, not a core constant expression, as initializer.

A constexpr specifier used in an object declaration declares the object as const. Such an object shall have literal type and shall be initialized. If it is initialized by a constructor call, that call shall be a constant expression. Otherwise, or if a constexpr specifier is used in a reference declaration, every full-expression that appears in its initializer shall be a constant expression. [Note: Each implicit conversion used in converting the initializer expressions and each constructor call used for the initialization is part of such a full-expression. - end note]

Upvotes: 6

Related Questions