When trying to verify an array of fixed-length character strings is sorted at compile time, there is odd behavior in using strncmp.
If the validation function references the global array, all values of N seem to work.
#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");
}
However, if using a function template, only values where N is less than or equal to 8 seem to work.
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");
}
For example, with N = 9, the template approach will error with...
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) {
| ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
Unfortunately for me, I need N to equal 16 and I have multiple global STRINGS arrays to verify, so I was hoping the function template would allow me to check each one with static assertion.