c++ - 局部常量变量不是 constexpr 可评估的,但不知道为什么
问题描述
我正在尝试将 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)
编译失败:
错误 C2131:表达式未计算为常量
注意:失败是由在其生命周期之外读取变量引起的
注意:请参阅“字节”的用法
我在 StackOverflow 上阅读了关于参数可能无法在编译时评估的主题,(这就是为什么我将大部分参数切换到模板变量,因此 100% 保证它们是编译时)但在这种情况下它不会为什么它给出错误似乎是合乎逻辑的。该bytes
值取决于编译时值,字节也是常数。
为什么它会超出它的生命周期?如果我说"somestring"
而不是变量,bytes
那么它可以完美编译。这里有什么不可评估的?
解决方案
constexpr
在函数声明上不需要所有的求值路径都指向一个常量表达式。函数调用的结果是否constexpr
取决于输入参数。
假设您的 Hash 函数如下所示:
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;
}
推荐阅读
- javascript - ExtJS 链式存储过滤器不过滤
- javascript - React 钩子:用单个钩子包装多个钩子实例的最佳实践是什么?
- android - Qt >= 5.14:如何在 QtCreator 中禁用 AAB 创建(仅生成 armv7)
- javascript - 无法在 Javascript 中调用函数
- sqlanywhere - 我在哪里可以找到告诉我的 SQLAnywhere ASA6532 错误?
- javascript - onclick 没有调用函数
- tesseract - 如何使用 WinAppDriver GetScreenshot 方法中的 Tesseract LoadTiffFromMemory 加载图像?
- javascript - 如何在不同时播放所有歌曲的情况下循环播放歌曲列表(JavaScript)?
- excel - 用于单元格粗边框的 VBA 宏(在评估范围内的单元格是否大于 0 后,需要偏移)
- r - 在 Tcl/TK R 包中模拟按钮点击