【问题标题】:Infinite recursion of constexpr template functionconstexpr 模板函数的无限递归
【发布时间】:2019-05-10 23:56:47
【问题描述】:

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

但是当我将 position 设为 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");

问题出在哪里?

【问题讨论】:

  • 请添加令人震惊的实例化。

标签: c++ templates generics constants constexpr


【解决方案1】:

三元运算并不能避免模板实例化。

所以当Position &gt;= N - 1 时,你仍然实例化fnv1a_internal&lt;N, Position + 1&gt; 实例化fnv1a_internal&lt;N, Position + 2&gt; 等等。

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

【讨论】:

    猜你喜欢
    • 2021-01-16
    • 1970-01-01
    • 2018-08-19
    • 2020-11-10
    • 2018-07-10
    • 1970-01-01
    • 1970-01-01
    • 2022-11-03
    • 2015-04-19
    相关资源
    最近更新 更多