验证固定长度字符串数组在编译时是否已排序

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 数组需要验证,所以我希望函数模板允许我使用静态断言检查每个数组。

编译器资源管理器链接

HTN*_*TNW 5

strncmp甚至std::strncmpconstexpr符合 C++ 标准。所以,实际上,你的代码根本不应该工作。它似乎strncmp是一个 GCC/Clang 魔法内置函数,所以这可能就是为什么会发生所有奇怪的行为(但你的编译器实际上是有错误的,因为它会让你的任何示例编译)。

自己写一个strncmp就是constexpr。另外,标记STRINGSconstexpr(请参阅注释中的混乱)。