0x4*_*D18 2 c++ generics templates 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);
}
Run Code Online (Sandbox Code Playgroud)
但是当我将 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);
}
Run Code Online (Sandbox Code Playgroud)
在实例化时,它将无法编译,编译器会抱怨函数超出递归限制。
这些函数旨在与这样的字符串文字一起使用:
uint32_t hash = fnv1a("Hello world");
Run Code Online (Sandbox Code Playgroud)
问题出在哪儿?
三元操作不会避免模板实例化。
所以当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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
104 次 |
| 最近记录: |