Consider the following constexpr function, static_strcmp, which uses C++17's constexpr char_traits::compare function:
#include <string>
constexpr bool static_strcmp(char const *a, char const *b)
{
return std::char_traits<char>::compare(a, b,
std::char_traits<char>::length(a)) == 0;
}
int main()
{
constexpr const char *a = "abcdefghijklmnopqrstuvwxyz";
constexpr const char *b = "abc";
constexpr bool result = static_strcmp(a, b);
return result;
}
godbolt shows this gets evaluated at compile-time, and optimised down to:
main: xor eax, eax ret
Remove constexpr from bool result:
If we remove the constexpr from constexpr bool result, now the call is no longer optimised.
#include <string>
constexpr bool static_strcmp(char const *a, char const *b)
{
return std::char_traits<char>::compare(a, b,
std::char_traits<char>::length(a)) == 0;
}
int main()
{
constexpr const char *a = "abcdefghijklmnopqrstuvwxyz";
constexpr const char *b = "abc";
bool result = static_strcmp(a, b); // <-- note no constexpr
return result;
}
godbolt shows we now call into memcmp:
.LC0: .string "abc" .LC1: .string "abcdefghijklmnopqrstuvwxyz" main: sub rsp, 8 mov edx, 26 mov esi, OFFSET FLAT:.LC0 mov edi, OFFSET FLAT:.LC1 call memcmp test eax, eax sete al add rsp, 8 movzx eax, al ret
Add a short circuiting length check:
if we first compare char_traits::length for the two arguments in static_strcmp before calling char_traits::compare, without constexpr on bool result, the call is optimised away again.
#include <string>
constexpr bool static_strcmp(char const *a, char const *b)
{
return
std::char_traits<char>::length(a) == std::char_traits<char>::length(b)
&& std::char_traits<char>::compare(a, b,
std::char_traits<char>::length(a)) == 0;
}
int main()
{
constexpr const char *a = "abcdefghijklmnopqrstuvwxyz";
constexpr const char *b = "abc";
bool result = static_strcmp(a, b); // <-- note still no constexpr!
return result;
}
godbolt shows we're back to the call being optimised away:
main: xor eax, eax ret
- Why does removing
constexprfrom the initial call tostatic_strcmpcause the constant evaluation to fail? - Clearly even without
constexpr, the call tochar_traits::lengthis evaluated at compile time, so why not the same behaviour withoutconstexprin the first version ofstatic_strcmp?