// 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));
}
}
正如您所看到的,函数本身和数组是constexpr
,因此应该在编译时进行评估。 MSVC编译器吐出“表达式未评估为常量”的错误。这是为什么?
答案 0 :(得分:2)
你应该删除多余的演员阵容:
// now we only need one static cast
constexpr uint32_t crc32_impl(const char * p, size_t len, uint32_t crc) {
return len ?
crc32_impl(p + 1, len - 1, (crc >> 8) ^ crc_table[(crc & 0xFF) ^ static_cast< unsigned char >(*p)])
: crc;
}
constexpr uint32_t crc32(const char * data, size_t length)
{
return ~crc32_impl(data, length, ~0);
}
// we can obtain string literal array size at one go
template<size_t V_array_items_count> constexpr uint32_t
generate(const char ( & str )[V_array_items_count])
{
return crc32(str, V_array_items_count - 1);
}
或者,如果您希望保持crc32接口接受uint8_t
或byte
,那么您可能需要在编译时构建相应的副本数组。