Рассмотрим следующую функцию constexpr
, static_strcmp
, которая использует функцию C ++ 17 constexpr
char_traits::compare
:
#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 показывает, что это оценивается во время компиляции и оптимизируется до:
main:
xor eax, eax
ret
Удалить constexpr
из bool result
:
Если мы удалим constexpr
из constexpr bool result
, теперь вызов больше не оптимизируется.
#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 показывает, что мы теперь вызываем в 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
Добавить короткое замыкание length
проверить:
если мы сначала сравним char_traits::length
для двух аргументов в static_strcmp
перед вызовом char_traits::compare
, без constexpr
на bool result
, вызов будет оптимизирован еще раз.
#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 показывает, что мы вернулись к оптимизируемому вызову:
main:
xor eax, eax
ret
- Почему удаление
constexpr
из начального вызова static_strcmp
приводит к сбою постоянной оценки?
- Очевидно, что даже без
constexpr
вызов char_traits::length
оценивается во время компиляции, так почему бы не повторить то же поведение без constexpr
в первой версии static_strcmp
?