我试图将int作为参数并分别对其字节进行操作,例如,采用0xDEADF00D并一一处理每个字节:0xDE 0xAD 0xF0 0x0D
为此,我完成了以下代码:
template <int state, int seed>
constexpr static uint32_t CalculateRandomFromState()
{
const char bytes[4] = {
(state >> 24) & 0xFF,
(state >> 16) & 0xFF,
(state >> 8) & 0xFF,
state & 0xFF,
};
constexpr auto value = Compiletime::Hash<seed, sizeof(bytes)>(bytes);
return value;
}
HashFn的信号是:
template <const uint32_t seed, const uint32_t size = NULL>
constexpr uint32_t Hash(const char* message)
编译失败,并显示以下信息:
错误C2131:表达式的计算结果不为常量
注意:失败是由于变量寿命之外的读取而引起的
注意:请参阅“字节”的用法
我已经在StackOverflow上阅读了有关参数可能无法在编译时进行评估的主题,(这就是为什么我将大多数参数切换为模板变量的原因,因此100%确保了它们在编译时)< / em>,但在这种情况下,给出错误的原因似乎并不合逻辑。 bytes
值取决于编译时间值,字节也是一个常数。
为什么会超出生命周期?如果我说"somestring"
而不是变量bytes
,那么它可以完美编译。
这里有什么不可以持续评估的?
答案 0 :(得分:7)
constexpr
不需要所有求值路径都可以导致一个常量表达式。函数调用的结果是否为constexpr
取决于输入参数。
假设您的哈希函数如下所示:
template <uint32_t seed, uint32_t size>
constexpr uint32_t Hash(const char* message)
{
uint32_t rc = seed;
for (uint32_t i = 0; i < size; ++i)
rc += message[i];
return rc;
}
如果message
是一个常数表达式,它将得出一个常数表达式。
但是您要使用非恒定表达式来调用它:
const char bytes[4] = {
(state >> 24) & 0xFF,
(state >> 16) & 0xFF,
(state >> 8) & 0xFF,
state & 0xFF,
};
constexpr auto value = Compiletime::Hash<seed, sizeof(bytes)>(bytes);
每次调用Hash(bytes)
时,bytes
的地址可能会不同。
您只需声明bytes
constexpr
,即可使其生效:
template <int state, int seed>
constexpr static uint32_t CalculateRandomFromState()
{
constexpr char bytes[4] = {
(state >> 24) & 0xFF,
(state >> 16) & 0xFF,
(state >> 8) & 0xFF,
state & 0xFF,
};
constexpr auto value = Compiletime::Hash<seed, sizeof(bytes)>(bytes);
return value;
}