// codenz.cpp
constexpr uint32_t Hashes[] =
{
// ntdll
crc32::generate("memcpy"),
// kernel32
crc32::generate("MessageBoxA")
};
// hash.hpp
#include <cstring>
#include <cstdint>
namespace crc32
{
// Generate CRC lookup table
template <unsigned c, int k = 8>
struct f : f<((c & 1) ? 0xedb88320 : 0) ^ (c >> 1), k - 1> {};
template <unsigned c> struct f<c, 0> { enum { value = c }; };
#define A(x) B(x) B(x + 128)
#define B(x) C(x) C(x + 64)
#define C(x) D(x) D(x + 32)
#define D(x) E(x) E(x + 16)
#define E(x) F(x) F(x + 8)
#define F(x) G(x) G(x + 4)
#define G(x) H(x) H(x + 2)
#define H(x) I(x) I(x + 1)
#define I(x) f<x>::value ,
constexpr unsigned crc_table[] = { A(0) };
// Constexpr implementation and helpers
constexpr uint32_t crc32_impl(const uint8_t* p, size_t len, uint32_t crc) {
return len ?
crc32_impl(p + 1, len - 1, (crc >> 8) ^ crc_table[(crc & 0xFF) ^ *p])
: crc;
}
constexpr uint32_t crc32(const uint8_t* data, size_t length) {
return ~crc32_impl(data, length, ~0);
}
constexpr size_t strlen_c(const char* str) {
return *str ? 1 + strlen_c(str + 1) : 0;
}
constexpr uint32_t generate(const char* str) {
return crc32((uint8_t*)str, strlen_c(str));
}
}
As you can see the function itself and the array is constexpr and thus should be evaluated at compile time. The MSVC compiler spits out an error that "expression did not evaluate to a constant". Why is that?