ConstexPR模板功能的无限递归

Infinite recursion of constexpr template function

本文关键字:无限 递归 功能 ConstexPR      更新时间:2023-10-16

i用constexpr函数在C 中实现了FNV-1A,但我遇到了一个奇怪的问题。

此版本无问题而起作用:

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

但是,当我将位置作为const通用参数时,像这样

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");

问题在哪里?

三元操作不避免模板实例化。

因此,当Position >= N - 1时,您仍然实例化 fnv1a_internal<N, Position + 1> instantiat fnv1a_internal<N, Position + 2>等。

自C 17以来,您可以使用if constexpr

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