When combing FDIS, I found three places that determine where the expression constexpr should be evaluated during translation.
Section 3.6.2 Initialization of non-local variables , paragraph 2 says that if an object with a static or local storage time of the stream is initialized by the constexpr constructor, then the constructor is evaluated during translation:
Continuous initialization is performed:
- if an object with a statics or duration of the thread storage is initialized by a constructor call, if the constructor is a
constexpr constructor, if all constructor arguments are constant expressions (including conversions), and if after replacing the function call (7.1) .5), each constructor call and the full expression in mem -initializers is a constant expression;
. Section 7.1.5. The constexpr specifier , clause 9 says that if an object declaration includes a constexpr , this object is evaluated during translation (i.e. it is a literal):
A constexpr qualifier used in declaring an object declares the object as const. Such an object must be of literal type and must be initialized. If it is initialized with a constructor call, this call must be a constant expression (5.19). Otherwise, each complete expression that appears in its initializer must be a constant expression. Each implicit conversion used in the conversion of initializer expressions and each constructor call used for initialization must be one of the allowed in the constant expression (5.19).
Ive heard people claim that this paragraph leaves room for implementation to delay initialization until runtime if the effect cannot be detected during translation due to, say, static_assert . This is probably not an accurate view, because, regardless of whether the value is initialized during translation, it is observable in some cases. This view is reinforced by Section 5.19 Permanent Expressions , paragraph 4:
[Note. Although in some contexts constant expressions must be evaluated during program translation, others may be evaluated during program execution. Since this international standard does not impose any restrictions on the accuracy of floating point operations, it is unclear whether evaluating a floating point expression during translation gives the result of the same result as evaluating the same expression (or the same operations with the same values) in program execution time ... - end note]
Section 9.4.2 Static data elements , paragraph 3 says that if a constant static data member of type literal is initialized by a constexpr function or constructor, then this function or constructor must be evaluated during translation:
If the static data member is of type const literal, its declaration in the class definition may indicate a logical or orthogonal initializer in which each initializer clause, which is an assignment expression, is a constant expression. The static literal data member can be declared in the class definition using the constexpr ; if so, his declaration specifies a logical or equal-initializer, in which each initializing clause, which is an assignment expression, is a constant expression. [Note. In both cases, the term can be displayed in constant expressions. - final note]
Interestingly, I did not find anything in FDIS, which required a constexpr expression to evaluate if its result was used as an array dimension. I am quite sure that the standard committee expects this to happen. But I could also skip this in my quest.
Outside of these conditions, the C ++ 11 standard allows calculations in design functions and constructors during translation. But that does not require it. Calculations may occur at run time. What kind of calculations that the compiler performs during translation is to a certain extent a matter of implementation quality.
In all three situations that I discovered, the trigger for estimating the translation time is based on the requirements of the target, using the result of calling constexpr . Regardless of whether constexpr function arguments are literals, they are never considered (although this is a prerequisite for a correct evaluation).
So, in order to get to the real point, it seems that the constexpr evaluation during the translation is started with:
- The implied argument of the object when resolving overload (section 13.3.1, paragraph 3) is either constexpr or requires a literal.
I hope this helps someone other than me. Thanks to everyone who contributed.