当试图验证固定长度字符串数组在编译时排序时,使用
strncmp
会出现奇怪的行为。
如果验证函数引用全局数组,N 的所有值似乎都有效。
#include <cstring>
#define N 8 // vary values of N
const char STRINGS[][N] = {"a", "b", "c"};
constexpr bool is_sorted_global() {
for (int i = 0; i < sizeof(STRINGS) / N - 1; i++) {
if (strncmp(STRINGS[i], STRINGS[i + 1], N) > 0) {
return false;
}
}
return true;
}
int main()
{
// always works for any N
static_assert(is_sorted_global(), "list is not sorted");
}
但是,如果使用函数模板,只有 N 小于或等于 8 的值才有效。
template<const char T[][N]>
constexpr bool is_sorted_t() {
for (int i = 0; i < sizeof(T) / N - 1; i++) {
if (strncmp(T[i], T[i+1], N) > 0) {
return false;
}
}
return true;
}
int main()
{
// only works for N <= 8
static_assert(is_sorted_t<STRINGS>(), "list not sorted");
}
例如,当 N = 9 时,模板方法会出错...
C:\msys64\mingw64\bin\g++.exe -fdiagnostics-color=always -g C:\Projects\helloworld\helloworld.cpp -o C:\Projects\helloworld\helloworld.exe
C:\Projects\helloworld\helloworld.cpp: In function 'int main()':
C:\Projects\helloworld\helloworld.cpp:34:39: error: non-constant condition for static assertion
34 | static_assert(is_sorted_t<STRINGS>(), "list is not sorted");
| ~~~~~~~~~~~~~~~~~~~~^~
C:\Projects\helloworld\helloworld.cpp:34:39: in 'constexpr' expansion of 'is_sorted_t<(& STRINGS)>()'
C:\Projects\helloworld\helloworld.cpp:23:25: error: 'strncmp(((const char*)(& STRINGS)), (((const char*)(& STRINGS)) + 9), 9)' is not a constant expression
23 | if (std::strncmp(T[i], T[i + 1], N) > 0) {
| ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
对我来说不幸的是,我需要 N 等于 16 并且我有多个全局字符串数组要验证,所以我希望函数模板允许我用静态断言检查每个数组。
strncmp
甚至std::strncmp
都不是constexpr
。所以,实际上,您的代码根本不应该工作。看起来 strncmp
是一个 GCC 魔法内置函数,所以这可能就是为什么所有奇怪的行为都在发生(但你的编译器实际上是错误的,因为你的任何示例都无法编译)。
写你自己的
strncmp
即constexpr
。此外,STRINGS
本身可能应该是constexpr
.