Локальная постоянная переменная не может быть оценена constexpr, но не может понять, почему - PullRequest
2 голосов
/ 26 марта 2019

Я пытаюсь взять 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;
}

Sig HnFn:

template <const uint32_t seed, const uint32_t size = NULL>
constexpr uint32_t Hash(const char* message)

Сбой компиляции с:

ошибка C2131: выражение не вычисленок константе

примечание: сбой был вызван чтением переменной вне ее времени жизни

примечание: см. использование 'байтов'

Я прочиталтемы в StackOverflow о параметрах могут быть не в состоянии оценить во время компиляции, (поэтому я переключил большинство своих параметров на переменную шаблона, так что на 100% гарантировано, что они находятся во время компиляции) , но в этом случае этоне кажется логичным, почему это дает ошибку.Значение bytes зависит от значения времени компиляции, а также байта является константой.

Почему оно выходит за пределы своего времени жизни?Если вместо переменной bytes я скажу, скажем, "somestring", то она отлично скомпилируется.Что тут не оценивается константой?

1 Ответ

7 голосов
/ 26 марта 2019

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;
}

Это приведет к константному выражениюiff 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;
}
...