N4140 §5.19 [expr.const]/p2, bullet 2.7.1, and p3:
2 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:
- [...]
- 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 ]
- 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;
- [...]
3 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 array bounds (8.3.4, 5.3.4), as bit-field lengths (9.6), as enumerator initializers if the underlying type is not fixed (7.2), and as alignments (7.6.2). —end note ]
In your code, N is a "non-volatile glvalue of integral or enumeration type", it refers to a "non-volatile const object with a preceding initialization", so applying the lvalue-to-rvalue conversion to it does not prevent the expression from being a core constant expression despite the absence of constexpr.
constintegral type can be used in a context where a constant expression is required. This feature was already in C++98. (Not sure about the combinationconst volatilethough.)const volatilespits a warning ing++actually. Re-edited the question. Just consider theconstversion, bothg++andclang++compile it with no warnings.constinstead ofconstexpre.g. in template meta - programming. From the answers I get, it looks likeconstbehaves similarly, and that's not the case. I don't remember where exactly I've read aboutconst, but it was explicitly mentioned that the initialization may be done at runtime. Then how can it be a compile-time constant? Is then the only difference betweenconstexprandconstthe fact thatconstexpris forced to be computed (if possible) at compile-time, whereasconstcan be deferred to run-time?