4

我正在尝试将多态类型作为映射中的键。

我想出了以下两个结构:

请注意,这Game是一个抽象类,我使用的数据结构是:

std::unordered_map<gamePtr,int> _allGames;

whilegamePtr是一个typedeffor:

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不是因为它试图复制 a unique_ptr(这是不可能的)而且我不知道如何克服它。很想听听一些建议(如果可能的话)。

编辑:比较器似乎也无法正常工作。如何使此地图unique_ptr作为键正常工作?

编辑2:

想出了:

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;
}

};

他们应该足够吗?

4

2 回答 2

4

该标准提供了一个规范,因此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提供比较托管指针的比较运算符。如果要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
}
于 2014-01-07T06:50:12.407 回答
0

game将by const 引用传递到std::hash::operator()

template<>
struct std::hash<std::unique_ptr<Game>> {
    size_t operator()(const std::unique_ptr<Game>& game) const;
}

这同样适用于cmp_games::operator()

于 2014-01-07T06:44:01.380 回答