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
twoEulersto 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.
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
constexprconstructor then the constructor is evaluated during translation:Section 7.1.5 The constexpr specifier, paragraph 9 says if an object declaration includes the
constexprspecifier, that object is evaluated during translation (i.e., is a literal):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: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:
Interestingly, I did not find anything in the FDIS that required a
constexprexpression 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
constexprcall. Whether or not the arguments to theconstexprfunction 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
constexprevaluation during translation is triggered by:I hope that’s helpful to someone besides me. Thanks to everyone who contributed.