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...
A constexpr function that is eligible to be evaluated at compile-time will only be evaluated at compile-time if the return value is used where a constant expression is required. Otherwise, compile-time evaluation is not guaranteed.
GCC (and other compilers) treat strlen as a 'constexpr' function as an extension to the language.
constexpr std::string While it's best to rely on string_views and not create unnecessary string copies, the example above shows that you can even create pass vectors of strings inside a constexpr function!
constexpr indicates that the value, or return value, is constant and, where possible, is computed at compile time. A constexpr integral value can be used wherever a const integer is required, such as in template arguments and array declarations.
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.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With