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

问题描述 投票:0回答:1

当试图验证固定长度字符串数组在编译时排序时,使用

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 并且我有多个全局字符串数组要验证,所以我希望函数模板允许我用静态断言检查每个数组。

编译器资源管理器链接

c++ sorting c-strings constexpr static-assert
1个回答
1
投票

strncmp
甚至
std::strncmp
都不是
constexpr
。所以,实际上,您的代码根本不应该工作。看起来
strncmp
是一个 GCC 魔法内置函数,所以这可能就是为什么所有奇怪的行为都在发生(但你的编译器实际上是错误的,因为你的任何示例都无法编译)。

写你自己的

strncmp
constexpr
。此外,
STRINGS
本身可能应该是
constexpr
.

© www.soinside.com 2019 - 2024. All rights reserved.