【发布时间】:2020-04-02 15:02:50
【问题描述】:
好的,代码如下:
#include <cstdio>
#include <cstdint>
template<typename T>
[[nodiscard]] constexpr bool
run_tests() noexcept
{
T const blah1[6]{4, 8, 15, 16, 23, 42};
T const blah2[6]{4, 8, 15, 16, 23, 42};
T const blah3[6]{};
if (__builtin_memcmp(blah1, blah2, 6 * sizeof(T)) != 0) {
return false;
}
if (__builtin_memcmp(blah1, blah3, 6 * sizeof(T)) == 0) {
return false;
}
return true;
}
int
main() noexcept
{
static_assert(run_tests<int8_t>());
// static_assert(run_tests<int64_t>());
if (run_tests<int8_t>()) {
printf("success\n");
}
else {
printf("failure\n");
}
if (run_tests<int64_t>()) {
printf("success\n");
}
else {
printf("failure\n");
}
return 0;
}
使用 Clang 10(在 Windows 上),它编译得很好,如果我运行它,我会得到:
success
success
正如我所料。如果我取消注释以下内容:
static_assert(run_tests<int64_t>());
我收到以下编译时错误:
error: static_assert expression is not an integral constant expression
这里有两件事很奇怪。首先是它可以与int8_t 和uint8_t 一起正常编译,但我提供的任何其他整数类型都会重现上述错误。其次,如果我注释掉这个:
if (__builtin_memcmp(blah1, blah3, 6 * sizeof(T)) == 0) {
return false;
}
它也可以与所有整数类型一起编译。因此,只有在数组不相等且不是 8 位的情况下才会出现此编译时错误。
想法?这对我来说似乎是一个错误,但我想在提交错误报告之前看看其他人的想法。作为参考,我尝试在启用 C++17 和 C++20 的情况下进行编译,并且我已经验证 Clang 10 将 __builtin_memcmp 实现为 constexpr (两者都使用 __has 宏,并且它作为 constexpr 在一些场景)。
【问题讨论】:
-
哪些文档让您相信
__builtin_memcmp应该是一个常量表达式? -
我在该链接中没有看到任何
__builtin_memcmp的结果是一个常量表达式。它需要一个常量表达式,但这就是我所看到的。 -
它大量使用 Libc++ 来支持 constexpr 函数。例如:github.com/llvm-mirror/libcxx/blob/…