2014-01-07 38 views
3

我試圖在映射中保存多態類型作爲鍵。std ::散列在無序映射中的唯一ptr

我想出了以下兩種結構:

注意Game是一個抽象類,我用的數據結構是:

std::unordered_map<gamePtr,int> _allGames; 

gamePtrtypedef爲:

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

通過引用'operator()'傳遞'unique_ptr'? – Nabla

+0

不管標準是否爲std :: unique_ptr定義了std :: hash?它在cppreference上:http://en.cppreference。com/w/cpp/memory/unique_ptr/hash – jogojapan

+0

@jogojapan在我看來,標準哈希由指針地址散列,而提問者想要散列指針指向的對象值,請參閱他們的'cmp_games'實現。 – Nabla

回答

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

Live demo


另一種選擇是改變現有的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 
} 
0

傳遞game通過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()