编译时哈希 - 模板推导顺序混乱
Compile time hash - confusion on template deduction order
我在其他主题中找到了这段代码
template<size_t N, size_t I = 0>
struct hash_calc
{
static constexpr size_t apply(const char(&s)[N])
{
return (hash_calc < N, I + 1 >::apply(s) ^ s[I]) * 16777619u;
};
};
template<size_t N>
struct hash_calc<N, N>
{
static constexpr size_t apply(const char(&s)[N])
{
return 2166136261u;
};
};
template<size_t N>
constexpr size_t hash(const char(&s)[N])
{
return hash_calc<N>::apply(s);
}
首先,我完全不明白为什么它不会以无限递归调用结束?据我了解,首先 hash_calc<N, I>
总是会调用自己,是什么导致它在 I
到达 N
时在 hash_calc<N, N>
中断? hash_calc<N, I>
的模板实例化在 N == I
时不会失败。
其次 - 我试图将 hash_calc<N, N>
结构复制粘贴到 hash_calc<N, I>
上,这会导致编译错误 error: 'hash_calc' is not a class template struct hash_calc<N, N>
。这是为什么?!
编辑:
下面修改后的代码不会在 msvc 或 gcc 下编译。我刚刚将一个模板放在另一个模板之上。发生什么事了?
template<size_t N>
struct hash_calc<N, N>
{
static constexpr size_t apply(const char(&s)[N])
{
return 2166136261u;
};
};
template<size_t N, size_t I = 0>
struct hash_calc
{
static constexpr size_t apply(const char(&s)[N])
{
return (hash_calc < N, I + 1 >::apply(s) ^ s[I]) * 16777619u;
};
};
template<size_t N>
constexpr size_t hashq(const char(&s)[N])
{
return hash_calc<N>::apply(s);
}
I am totally confused why it does not end being an infinite recursive call?
那么让我们一步步来看吧。
hashq<N>(const char(&s)[N])
呼叫 hash_calc<N>::apply(s);
.
那是:
template<size_t N, size_t I = 0>
struct hash_calc
{
static constexpr size_t apply(const char(&s)[N])
{
return (hash_calc < N, I + 1 >::apply(s) ^ s[I]) * 16777619u;
};
};
和 I==0
。
现在 hash_calc < N, I + 1 >::apply(s)
被调用,I==1
,这一直持续到 I==N
。那时
template<size_t N>
struct hash_calc<N, N>
{
static constexpr size_t apply(const char(&s)[N])
{
return 2166136261u;
};
};
被调用。并且递归结束。
Why is that?!
template<size_t N, size_t I = 0>
struct hash_calc
{
static constexpr size_t apply(const char(&s)[N])
{
return (hash_calc < N, I + 1 >::apply(s) ^ s[I]) * 16777619u;
};
};
是更一般的情况,它处理任何一对<N,I>
,而
template<size_t N>
struct hash_calc<N, N>
{
static constexpr size_t apply(const char(&s)[N])
{
return 2166136261u;
};
};
是它的特长,它只能处理<N,N>
的情况。
编译器首先需要一般情况,然后是特殊情况。
我在其他主题中找到了这段代码
template<size_t N, size_t I = 0>
struct hash_calc
{
static constexpr size_t apply(const char(&s)[N])
{
return (hash_calc < N, I + 1 >::apply(s) ^ s[I]) * 16777619u;
};
};
template<size_t N>
struct hash_calc<N, N>
{
static constexpr size_t apply(const char(&s)[N])
{
return 2166136261u;
};
};
template<size_t N>
constexpr size_t hash(const char(&s)[N])
{
return hash_calc<N>::apply(s);
}
首先,我完全不明白为什么它不会以无限递归调用结束?据我了解,首先 hash_calc<N, I>
总是会调用自己,是什么导致它在 I
到达 N
时在 hash_calc<N, N>
中断? hash_calc<N, I>
的模板实例化在 N == I
时不会失败。
其次 - 我试图将 hash_calc<N, N>
结构复制粘贴到 hash_calc<N, I>
上,这会导致编译错误 error: 'hash_calc' is not a class template struct hash_calc<N, N>
。这是为什么?!
编辑: 下面修改后的代码不会在 msvc 或 gcc 下编译。我刚刚将一个模板放在另一个模板之上。发生什么事了?
template<size_t N>
struct hash_calc<N, N>
{
static constexpr size_t apply(const char(&s)[N])
{
return 2166136261u;
};
};
template<size_t N, size_t I = 0>
struct hash_calc
{
static constexpr size_t apply(const char(&s)[N])
{
return (hash_calc < N, I + 1 >::apply(s) ^ s[I]) * 16777619u;
};
};
template<size_t N>
constexpr size_t hashq(const char(&s)[N])
{
return hash_calc<N>::apply(s);
}
I am totally confused why it does not end being an infinite recursive call?
那么让我们一步步来看吧。
hashq<N>(const char(&s)[N])
呼叫 hash_calc<N>::apply(s);
.
那是:
template<size_t N, size_t I = 0>
struct hash_calc
{
static constexpr size_t apply(const char(&s)[N])
{
return (hash_calc < N, I + 1 >::apply(s) ^ s[I]) * 16777619u;
};
};
和 I==0
。
现在 hash_calc < N, I + 1 >::apply(s)
被调用,I==1
,这一直持续到 I==N
。那时
template<size_t N>
struct hash_calc<N, N>
{
static constexpr size_t apply(const char(&s)[N])
{
return 2166136261u;
};
};
被调用。并且递归结束。
Why is that?!
template<size_t N, size_t I = 0>
struct hash_calc
{
static constexpr size_t apply(const char(&s)[N])
{
return (hash_calc < N, I + 1 >::apply(s) ^ s[I]) * 16777619u;
};
};
是更一般的情况,它处理任何一对<N,I>
,而
template<size_t N>
struct hash_calc<N, N>
{
static constexpr size_t apply(const char(&s)[N])
{
return 2166136261u;
};
};
是它的特长,它只能处理<N,N>
的情况。
编译器首先需要一般情况,然后是特殊情况。