Бесконечная рекурсия шаблонной функции constexpr - PullRequest
1 голос
/ 11 мая 2019

Я реализовал функцию FNV-1A в C ++ с функциями constexpr, но столкнулся со странной проблемой.

Эта версия работает без проблем:

template<size_t N>
static constexpr uint32_t fnv1a_internal(const char (&data)[N], size_t position, uint32_t state) {
    return position >= N - 1 ? state : fnv1a_internal(data, position + 1, (state ^ data[position]) * 16777619UL);
}

template<size_t N>
static constexpr uint32_t fnv1a(const char (&data)[N]) {
    return fnv1a_internal(data, 0, 2166136261UL);
}

Но когда я определяю позицию как общий аргумент, как этот

template<size_t N, size_t Position>
static constexpr uint32_t fnv1a_internal(const char (&data)[N], uint32_t state) {
    return Position >= N - 1 ? state : fnv1a_internal<N, Position + 1>(data, (state ^ data[Position]) * 16777619UL);
}

template<size_t N>
static constexpr uint32_t fnv1a(const char (&data)[N]) {
    return fnv1a_internal<N, 0>(data, 2166136261UL);
}

после создания экземпляра он не сможет скомпилироваться с компилятором, жалующимся на то, что функция превысила предел рекурсии.

Функции предназначены для использования со строковыми литералами, такими как:

uint32_t hash = fnv1a("Hello world");

Где проблема?

1 Ответ

3 голосов
/ 11 мая 2019

троичная операция не предотвращает создание экземпляра шаблона.

Поэтому, когда Position >= N - 1, вы все равно создаете экземпляр fnv1a_internal<N, Position + 1>, который создает экземпляр fnv1a_internal<N, Position + 2> и т. Д.

...