C++模板专用化 - 将其他整数类型委托给uint64_t

C++ template specialization - delegating other integer types to uint64_t

本文关键字:类型 uint64 整数 其他 专用 C++      更新时间:2023-10-16

>我正在尝试为整数类型实现自定义哈希函子以用于std::unordered_map.我想通过为无符号 64 位整数提供一个实现并通过强制转换/加宽将所有其他实现委托给该实现来做到这一点。

我过去已经成功地做到了这一点,只需为我想要的每种附加类型定义专业化:

template <typename T> struct custom_hash { size_t operator()(const T&) const };
template <> struct custom_hash<uint64_t> { size_t operator()(uint64_t x) const { /* ... */ }};
template <> struct custom_hash<int> { custom_hash<uint64_t> h; size_t operator()(int x) const { return h(x); }};
/* ... */

但是我想知道如何做到这一点,而无需对每种其他类型进行专业化。

我尝试了使用std::enable_ifstd::is_integral在 SO 上阅读的内容:

template <typename T> struct custom_hash { /* ... */ };
template <> struct custom_hash<uint64_t> { /* ... */ };
template <typename Int, typename = typename enable_if<is_integral<Int>::value, Int>::type>
struct custom_hash<Int> {
custom_hash<uint64_t> h;
size_t operator()(Int x) const {
return h(x);
}
};

但这没有用。叮当

抱怨

错误:类模板部分中的默认模板参数 专业化

错误:模板重新声明中的模板参数过多

我认为发生这种情况是因为该声明与先前没有定义的声明发生冲突。我对模板的了解不足以解决这个问题。

问题是模板专用化的所有模板参数都必须从基本模板中推导,而不是彼此推导。

如果你可以在基本模板中添加一个虚拟参数,或者在你控制的基础中进行特化,那么你就是黄金:

template <typename T, class = void>
struct custom_hash;
template <>
struct custom_hash<uint64_t>
{ size_t operator()(uint64_t x) const { /* ... */ }};
template <class T>
struct custom_hash<T, std::enable_if_t<std::is_integral<T>() && sizeof(T) <= sizeof(uint64_t)>
{ size_t operator()(int x) const {  custom_hash<uint64_t> h; return h(uint64_t(x)); }};