我正在尝试将多态类型作为地图中的键。
我想出了以下两种结构:
请注意Game
是一个抽象类,我使用的数据结构是:
std::unordered_map<gamePtr,int> _allGames;
虽然gamePtr
是typedef
,但是:
unique_ptr<Game>
template<>
struct std::hash<std::unique_ptr<Game>> {
size_t operator()(std::unique_ptr<Game> game) const {
return (std::hash<string>()(std::to_string(game->firstTeamFinalScore()) + game->firstTeam() + game->secondTeam()));
}
};
struct cmp_games {
bool operator() (std::unique_ptr<Game> game1, std::unique_ptr<Game> game2) const {
return *game1 == *game2;
}
};
cmp_games
比较器似乎工作正常,但std::hash
没有,因为它试图复制unique_ptr
(这是不可能的),我不知道如何克服它。
很想听到一些建议(如果可能的话)。
编辑:比较器似乎也无法正常工作。如何使用unique_ptr
作为密钥使此地图正常工作?
EDIT2:
提出:
template<>
struct std::hash<std::unique_ptr<Game>> {
size_t operator()(const std::unique_ptr<Game>& game) const {
return (std::hash<string>()(std::to_string(game->firstTeamFinalScore()) + game->firstTeam() + game->secondTeam()));
}
};
template<>
struct std::equal_to<std::unique_ptr<Game>> {
bool operator() (const std::unique_ptr<Game>& game1,const std::unique_ptr<Game>& game2) const {
return *game1 == *game2;
}
};
他们应该够吗?
答案 0 :(得分:4)
标准provides a specilization,以便std::hash<unique_ptr<T>>
与std::hash<T*>
相同。因此,为std::hash<Game *>
提供专业化。例如:
#include <iostream>
#include <memory>
#include <unordered_map>
#include <cstdlib>
struct foo
{
foo(unsigned i) : i(i) {}
unsigned i;
};
namespace std {
template<>
struct hash<foo *>
{
size_t operator()(foo const *f) const
{
std::cout << "Hashing foo: " << f->i << '\n';
return f->i;;
}
};
}
int main()
{
std::unordered_map<std::unique_ptr<foo>, int> m;
m.insert(std::make_pair(std::unique_ptr<foo>(new foo(10)), 100));
m.insert(std::make_pair(std::unique_ptr<foo>(new foo(20)), 200));
}
另一种选择是更改现有的std::hash
专精,以便通过引用获取unique_ptr
。
size_t operator()(std::unique_ptr<Game> const& game) const
// ^^^^^^ no more copying
编辑: std::unique_ptr
提供了比较托管指针的comparison operators。如果您希望unordered_map
测试Game
个对象本身是否相等,请提供operator==
重载而非专门化std::equal_to
inline bool operator==(const std::unique_ptr<Game>& game1,
const std::unique_ptr<Game>& game2)
{
return *game1 == *game2;
}
这反过来要求你为Game
提供了一个等于运算符(或者你可以将逻辑添加到上面的函数中)。
inline bool operator==(Game const& game1, Game const& game2)
{
return // however you want to compare these
}
答案 1 :(得分:0)
将const game
传递给std::hash::operator()
:
template<>
struct std::hash<std::unique_ptr<Game>> {
size_t operator()(const std::unique_ptr<Game>& game) const;
}
同样适用于cmp_games::operator()
。