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...
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:
shall be ... converted constant expression
or shall be ... constant expression
is used, such as an array bound.constexpr
as I outline above.