200 .cpp),它使用函数 hashCode() 返回哈希值:- class B01{ //a class //..... complex thing ..-6ren">
gpt4 book ai didi

c++ - 使 std 的数据结构默认使用我现有的非静态哈希函数 "hashCode()"

转载 作者:可可西里 更新时间:2023-11-01 15:36:52 25 4
gpt4 key购买 nike

我有一个中等大小的代码库 (>200 .cpp),它使用函数 hashCode() 返回哈希值:-

class B01{  //a class
//..... complex thing ....
public: size_t hashCode(){ /* hash algorithm #H01 */}
};
class B02{ //just another unrelated class
//..... complex thing ....
public: size_t hashCode(){/* #H02 */} //This is the same name as above
};

我已经在不同的地方使用过它,例如在我的自定义数据结构中。它运行良好。

现在,我想让std::数据结构识别的hash算法:-

这是我应该做的:-(修改自 cppreference ,我将此代码称为 #D)。

//#D
namespace std {
template<> struct hash<B01> {
std::size_t operator()(const B01& b) const {
/* hash algorithm #H01 */
}
};
}

如果我在每个类(B01B02、...)中插入 block #D(具有适当的实现),我可以打电话:-

std::unordered_set<B01> b01s;
std::unordered_set<B02> b02s;

传递第二个模板参数,
我的哈希算法 (#H01) 将被调用。 (按默认)

问题

让它识别我所有的B01::hashCode, B02::hashCode, ...,
我是否必须将 block #D 插入到所有 200 多个 Bxx.h 中?

我可以只添加一个单个 block #D(在顶部标题中吗?)
并从那里重新路由 std::anyDataStructure 以尽可能调用hashCode()

//pseudo code
namespace std{
template<> struct hash<X> {
std::size_t operator()(const X& x) const { // std::enable_if??
if(X has hashCode()){ //e.g. T=B01 or B02
make this template highest priority //how?
return hashCode();
}else{ //e.g. T=std::string
don't match this template;
}
}
};
}

对我来说这听起来像是一个 SFINAE 问题。

旁注: The most similar question在 SO 中没有询问如何实现这一点。

编辑(我为什么不直接重构它?;2017 年 2 月 3 日)

  • 我不知道强力重构是否是一条正确的道路。我想可能有更好的方法。
  • hashCode() 是我的家。我在情感上依恋它。
  • 我希望我的代码尽可能简洁明了。 std:: block 是脏的。
  • 这可能只是我的好奇心。如果我固执地不重构我的代码,C++ 能走多远?

最佳答案

不一定非要这样,你也可以有一个仿函数:

struct MyHash {
template <class T>
auto hashCode(const T & t, int) const -> decltype(t.hashCode()) {
return t.hashCode();
}
template <class T>
auto hashCode(const T & t, long) const -> decltype(std::hash<T>{}(t)) {
return std::hash<T>{}(t);
}

template <class T>
auto operator()(const T & t) const -> decltype(hashCode(t,42)) {
return hashCode(t,42);
}
};

并且有一个 std::unordered_set 的别名,MyHash 作为散列类型:

template <class Key>
using my_unordered_set = std::unordered_set<Key, MyHash>;

如果您还希望能够提供 Equal 仿函数和分配器,则可以更完整:

template<
class Key,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator<Key>
>
using my_unordered_set = std::unordered_set<Key, MyHash, KeyEqual, Allocator>;

然后像使用 std::unordered_set 一样使用它(与任何 Bxx):

int main() {
my_unordered_set<B01> b01s;
my_unordered_set<B02> b02s;

// or lonely with your type:
B01 b01{/*...*/};
std::cout << MyHash{}(b01) << std::endl;

// or any other:
std::string str{"Hello World!"};
std::cout << MyHash{}(str) << std::endl;
}

概念

如果可以使用concepts ,它们可以让你按照你想要的方式专门化 std::hash 类:

template <class T>
concept HashCodeConcept = requires(T const & t)
{
{t.hashCode()} -> std::same_as<std::size_t>;
};

namespace std {
template <HashCodeConcept T>
struct hash<T> {
std::size_t operator()(const T& t) const {
return t.hashCode();
}
};
}

关于c++ - 使 std 的数据结构默认使用我现有的非静态哈希函数 "hashCode()",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41867111/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com