我正在尝试为与 std::unordered_map
一起使用的整数类型实现自定义散列仿函数。为此,我想为无符号 64 位整数提供一个实现,并通过转换/扩展将所有其他实现委托(delegate)给该实现。
我过去通过为我想要的每个额外类型定义特化成功地做到了这一点:
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); }};
/* ... */
但我想知道如何在不对每个其他类型进行专门化的情况下执行此操作。
我试过了 something I read on SO使用 std::enable_if
和 std::is_integral
:
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);
}
};
但这没有用。 Clang 提示
error: default template argument in a class template partial specialization
和
error: too many template parameters in template redeclaration
我认为发生这种情况是因为声明与之前没有定义的声明发生冲突。我对模板了解不够,无法解决这个问题。
最佳答案
问题是模板特化的所有模板参数都必须从基本模板中推导出来,而不是从彼此推导出来。
如果你可以在基础模板中添加一个虚拟参数,或者在你控制的基础中进行特化,那么你就是黄金:
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)); }};
关于C++ 模板特化 - 将其他整数类型委托(delegate)给 uint64_t,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57452127/