>以粗体显示更新
我正在为函数指针表编写一个哈希函数,其限制是函数指针和函数表的结构无法修改(即它们已发布给第三方(。基于std::hash 可以用于哈希函数指针吗?,std::hash 可用于函数指针。采用它,它会产生以下解决方案。
这个解决方案的乏味之处在于,每次我们向 FuncPointer 结构添加新的 API 时,我们都必须修改哈希专用化以添加相应的更改(即 hashFunc(hashedValue, pFuncs->func3( (。
我想知道是否有更好的方法来实现函数指针的这种哈希,从而避免对哈希专业化的连续修改?
typedef void (*func_type1) (int);
typedef void (*func_type2) (double);
typedef struct FuncPointers
{
func_type1 func1;
func_type2 func2;
...
} FuncPointers;
template <typename T> void hashFunc (size_t & HashedValue, T funcPointer)
{
std::hash<T> hash;
HashedValue ^= hash(funcPointer); // the XOR operator is randomly picked
}
namespace std
{
template<> struct hash<FuncPointers>
{
size_t operator()(FuncPointers *pFuncs)
{
size_t hashedValue = 0;
hashFunc(hashedValue, pFuncs->func1);
hashFunc(hashedValue, pFuncs->func2);
...
return hashedValue;
}
};
}
从这个开始: https://stackoverflow.com/a/7115547/1774667
它提供了一个hash_tuple::hash<Tuple>
,它是一个有效的体面质量哈希器(具有组合和递归支持std::tuple
!
接下来,更改FuncPointers
如下所示:
struct FuncPointers:std::tuple<func_type1, func_type2 /*, ...*/> {
// optional:
func_type1 func1() const { return std::get<0>(*this); }
func_type1& func1() { return std::get<0>(*this); }
//...
};
namespace std {
template<>
struct hash<FuncPointers> {
template<typename... Ts>
std::size_t operator()( std::tuple<Ts...> const& funcs ) const {
return hash_tuple::hash<std::tuple<Ts...>>{}(funcs);
}
};
}
这会将您的std::hash<FuncPointers>
重定向到在FuncPointers
的父级上调用hash_tuple::hash<std::tuple<...>>
。 如果您不想从std::tuple
继承,将其更改为has-a而不是is-a关系应该很容易。
可选的func()
访问器使您更接近旧接口(只需要添加()
(,但也添加了样板。
另一种选择是:
template<unsigned N>
auto func() const->decltype( std::get<N>(*this) ){ return std::get<N>(*this); }
template<unsigned N>
auto& func()->decltype( std::get<N>(*this) ){ return std::get<N>(*this); }
它将funcPointers.func1
更改为funcPointers.func<1>()
,但是当您添加新func
时会摆脱大量的样板,并且与funcPointers
的旧界面非常相似。
如果没有太多代码使用旧接口,则使用 std::get<N>()
是有意义的。
如果您的名称比 func1
更具描述性,并且您仅将其用于示例,则可以将函数名称的枚举与上述std::get
或func<X>
一起使用。 如果你使用func<X>
你甚至可以让它类型安全(强制使用命名函数(。
最好让你的FuncPointers
成为std::tuple<func_type1, func_type2>
。然后看到这个关于哈希的答案。
顺便说一句,typedef struct FuncPointers { } FuncPointers
是一种在C++中从来不需要的C主义。