Where in the C++11 standard does it specify when a constexpr function can be evaluated during translation?
c++, c++11, constexpr
Solution
By combing the FDIS I have found three places that specify where a constexpr expression must be evaluated during translation.
Section 3.6.2 Initialization of non-local variables, paragraph 2 says if an object with static or thread local storage duration is initialized with a `constexpr` constructor then the constructor is evaluated during translation:
Constant initialization is performed:
- if an object with static or thread storage duration 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 function invocation substitution (7.1.5), every constructor call and full-expression in the mem-initializers is a constant expression;
Section 7.1.5 The constexpr specifier, paragraph 9 says if an object declaration includes the `constexpr` specifier, that object is evaluated during translation (i.e., is a literal):
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 (5.19). Otherwise, every full-expression that appears in its initializer shall be a constant expression. Each implicit conversion used in converting the initializer expressions and each constructor call used for the initialization shall be one of those allowed in a constant expression (5.19).
I’ve heard people argue that this paragraph leaves room for an implementation to postpone the initialization until runtime unless the effect can be detected during translation due to, say, a `static_assert`. That is probably not an accurate view because whether a value is initialized during translation is, under some circumstances, observable. This view is reinforced by Section 5.19 Constant 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 imposes no restrictions on the accuracy of floating-point operations, it is unspecified whether the evaluation of a floating-point expression during translation yields the same result as the evaluation of the same expression (or the same operations on the same values) during program execution... — end note ]
Section 9.4.2 Static data members, paragraph 3 says if a const static data member of literal type is initialized by a constexpr function or constructor, then that function or constructor must be evaluated during translation:
If a static data member is of const literal type, its declaration in the class definition can specify a brace-orequal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. A static data member of literal type can be declared in the class definition with the `constexpr` specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [ Note: In both these cases, the member may appear in constant expressions. — end note ]
Interestingly, I did not find anything in the FDIS that required a `constexpr` expression to be evaluated if its result is used as an array dimension. I'm quite sure the standard committee expects that to be the case. But I also could have missed that in my search.
Outside of those circumstances the C++11 standard allows computations in constexpr functions and constructors to be performed during translation. But it does not require it. The computations could occur at runtime. Which computations the compiler performs during translation are, to a certain extent, a quality of implementation question.
In all three of the situations I located, the trigger for translation-time evaluation is based on the requirements of the target using the result of the `constexpr` call. Whether or not the arguments to the `constexpr` function are literal is never considered (although it is a pre-requisite for valid evaluation).
So, to get to the real point of this, it appears that `constexpr` evaluation during translation is triggered by:
- The implied object argument during overload resolution (Section 13.3.1 Paragraph 3) is either constexpr or requires a literal.
I hope that's helpful to someone besides me. Thanks to everyone who contributed.
Problem
Just because a function (or constructor)... - is declared constexpr and - the function definition meets the constexpr requirements ...doesn't mean that the compiler will evaluate the constexpr function during translation. I've been looking through the C++11 FDIS (N3242, available at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/) to try and determine two things: - When is the compiler obligated to evaluate a constexpr function during translation? - When is the compiler allowed to evaluate a constexpr function during translation? Section 5.19 Paragraph 1 says that constant expressions can be evaluated during translation. As far as I can comprehend, the remainder of Section 5.19 sets forth the rules for what is valid in the definition of a constexpr function. I understand that I can force constexpr evaluation during translation by declaring the result of the constexpr function as constexpr. Like this: ``` // Declaration constexpr double eulers_num() { return 2.718281828459045235360287471; } // Forced evaluation during translation constexpr double twoEulers = eulers_num() * 2.0; static_assert(twoEulers > 5.0, "Yipes!"); ``` So far I've been unable to find the paragraphs in the FDIS that: - Force `twoEulers` to be evaluated during translation or - Specify other situations when the compiler may or must evaluate a constexpr function during translation. What I'm particularly interested in discovering is whether constexpr evaluation during translation is triggered by: - When all parameters passed to the constexpr function are literals, or - The implied object argument during overload resolution (Section 13.3.1 Paragraph 3) is either constexpr or requires a literal (such as for array dimensions), or - Something else entirely. Please, if possible, in your responses cite sections of the FDIS that I can look up or key phrases I can search in the FDIS. The English in the standard is somewhat obtuse, so I may have been reading the relevant paragraphs and have entirely missed their meaning or intent.