Nat*_*ger 2 c++ sorting c-strings static-assert constexpr
当尝试验证固定长度字符串数组在编译时是否已排序时,使用 时会出现奇怪的行为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");
}
Run Code Online (Sandbox Code Playgroud)
但是,如果使用函数模板,则只有 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");
}
Run Code Online (Sandbox Code Playgroud)
例如,当 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) {
| ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
不幸的是,对我来说,我需要 N 等于 16,并且我有多个全局 STRINGS 数组需要验证,所以我希望函数模板允许我使用静态断言检查每个数组。
strncmp甚至std::strncmp不constexpr符合 C++ 标准。所以,实际上,你的代码根本不应该工作。它似乎strncmp是一个 GCC/Clang 魔法内置函数,所以这可能就是为什么会发生所有奇怪的行为(但你的编译器实际上是有错误的,因为它会让你的任何示例编译)。
自己写一个strncmp就是constexpr。另外,标记STRINGS为constexpr(请参阅注释中的混乱)。