c++ - constexpr模板函数的无限递归

标签 c++ templates generics constants constexpr

我用 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>它实例化 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);
    }
}

关于c++ - constexpr模板函数的无限递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56086113/

相关文章:

c++ - 忽略一行输入中的某些输入

c++ - 将函数模板特化传递给可变参数模板函数

c++ - 通过来自任意索引的参数包初始化 std::array

C#泛型B+树

c# - 为所有泛型声明一次实现类型?

c# - 无法使用多个泛型类型获取接口(interface)/类的类型?

c++ - 使用类似枚举的类,或具有特定值

C++ 是否可以使用对变量的引用来简化这种嵌套循环模式?

c++ - 动态创建对象并将它们添加到链表中

c++ - 部分类特化只是编写完整特化的另一种方式吗?