局部常量变量不是constexpr可评估的,但无法弄清楚原因

问题描述 投票:2回答:1

我正在尝试将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:表达式未计算为常量

注意:失败是由在其生命周期之外读取变量引起的

注意:看看'bytes'的用法

我已经在StackOverflow上阅读了关于参数可能无法在编译时进行评估的主题,(这就是我将大部分参数切换到模板变量的原因,因此它100%保证它们是编译时间)但在这种情况下它没有'似乎是合乎逻辑的,它给出了一个错误。 bytes值取决于编译时间值,字节也是常量。

为什么它会超出它的一生?如果我说让我们说"somestring"而不是变量bytes然后它完美编译。什么不是常数可评估在这里?

c++ visual-c++ c++17 constexpr
1个回答
7
投票

函数声明中的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;
}
© www.soinside.com 2019 - 2024. All rights reserved.