局部常量变量不是 constexpr 可评估的,但无法弄清楚为什么
Local constant variable is not constexpr evaluatable, but can't figure out why
我正在尝试将 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 的 sig 是:
template <const uint32_t seed, const uint32_t size = NULL>
constexpr uint32_t Hash(const char* message)
编译失败:
error C2131: expression did not evaluate to a constant
note: failure was caused by a read of a variable outside its lifetime
note: see usage of 'bytes'
我在 Whosebug 上阅读了有关参数可能无法在编译时求值的主题,(这就是为什么我将大部分参数切换为模板变量的原因,因此可以 100% 保证它们是编译时间) 但在这种情况下,它给出错误的原因似乎不合逻辑。 bytes
值取决于编译时值,字节也是常量。
为什么它会超出它的生命周期?如果我让我们说 "somestring"
而不是变量 bytes
那么它编译完美。
这里有什么不是常量可评估的?
函数声明中的 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;
}
我正在尝试将 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 的 sig 是:
template <const uint32_t seed, const uint32_t size = NULL>
constexpr uint32_t Hash(const char* message)
编译失败:
error C2131: expression did not evaluate to a constant
note: failure was caused by a read of a variable outside its lifetime
note: see usage of 'bytes'
我在 Whosebug 上阅读了有关参数可能无法在编译时求值的主题,(这就是为什么我将大部分参数切换为模板变量的原因,因此可以 100% 保证它们是编译时间) 但在这种情况下,它给出错误的原因似乎不合逻辑。 bytes
值取决于编译时值,字节也是常量。
为什么它会超出它的生命周期?如果我让我们说 "somestring"
而不是变量 bytes
那么它编译完美。
这里有什么不是常量可评估的?
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;
}