Computing length of a C string at compile time. Is this really a constexpr?
c++, c++11, constexpr, standards, string-literals
Solution
Constant expressions are not guaranteed to be evaluated at compile time, we only have a non-normative quote from draft C++ standard section `5.19` Constant expressions that says this though:
[...]>[ Note: Constant expressions can be evaluated during translation.—end note ]
You can assign the result to `constexpr` variable to be sure it is evaluated at compile time, we can see this from Bjarne Stroustrup's C++11 reference which says (emphasis mine):
In addition to be able to evaluate expressions at compile time, we want to be able to require expressions to be evaluated at compile time; constexpr in front of a variable definition does that (and implies const):
For example:
constexpr int len1 = length("abcd") ;
Bjarne Stroustrup gives a summary of when we can assure compile time evaluation in this isocpp blog entry and says:
[...]The correct answer - as stated by Herb - is that according to the standard a constexpr function may be evaluated at compiler time or run time unless it is used as a constant expression, in which case it must be evaluated at compile-time. To guarantee compile-time evaluation, we must either use it where a constant expression is required (e.g., as an array bound or as a case label) or use it to initialize a constexpr. I would hope that no self-respecting compiler would miss the optimization opportunity to do what I originally said: "A constexpr function is evaluated at compile time if all its arguments are constant expressions."
So this outlines two cases where it should be evaluated at compile time:
- Use it where a constant expression is required, this would seem to be anywhere in the draft standard where the phrase `shall be ... converted constant expression` or `shall be ... constant expression` is used, such as an array bound.
- Use it to initialize a `constexpr` as I outline above.
Problem
I'm trying to compute the length of a string literal at compile time. To do so I'm using following code: ``` #include <cstdio> int constexpr length(const char* str) { return *str ? 1 + length(str + 1) : 0; } int main() { printf("%d %d", length("abcd"), length("abcdefgh")); } ``` Everything works as expected, the program prints 4 and 8. The assembly code generated by clang shows that the results are computed at compile time: ``` 0x100000f5e: leaq 0x35(%rip), %rdi ; "%d %d" 0x100000f65: movl $0x4, %esi 0x100000f6a: movl $0x8, %edx 0x100000f6f: xorl %eax, %eax 0x100000f71: callq 0x100000f7a ; symbol stub for: printf ``` My question: is it guaranteed by the standard that `length` function will be evaluated compile time? If this is true the door for compile time string literals computations just opened for me... for example I can compute hashes at compile time and many more...