2014-10-28 16 views
1

我使用的的鍵爲Currency,值爲貨幣價格的doubleCurrency是我製作的自定義類。這裏是一個版本,我曾嘗試:使用自定義鍵導致空值的C++ unordered_map

#ifndef CURRENCY_H 
#define CURRENCY_H 

#include "Nameable.h" 
#include <boost/uuid/uuid.hpp> 
#include <boost/uuid/uuid_generators.hpp> 
#include <boost/uuid/uuid_io.hpp> 
#include <boost/functional/hash.hpp> 
#include "BigDecimal.h" 
#include <iostream> 

/** 
* Represents a single currency. Can be used as keys in a map and as a general 
* identifier for determining what unit a value of money is. 
* @param name 
*/ 
class Currency: public Nameable { 
public: 
    Currency(std::string name) throw(NameAlreadyTakenException); 
    Currency(const Currency& orig); 
    virtual ~Currency(); 
    virtual std::string getName(); 
    virtual void setName(std::string name) throw(NameAlreadyTakenException); 
    inline bool operator==(const Currency& key) const { 
     return this->id == key.id; 
    } 

    // A custom hasher that I tried using. 
    struct currencyHasher 
     { 
     std::size_t operator()(const Currency& k) const 
     { 
      return boost::hash<boost::uuids::uuid>()(k.id); 
     } 
    }; 
    boost::uuids::uuid id; 
private: 

}; 
// A template specialization for Currency. 
namespace std { 
    template <> 
    struct hash<Currency> { 
     std::size_t operator()(const Currency& k) const { 
      cout<< boost::hash<boost::uuids::uuid>()(k.id)<<"\n"; 
      return boost::hash<boost::uuids::uuid>()(k.id); 
     } 
    }; 
} 
#endif /* CURRENCY_H */ 

這裏是實現:

#include "Currency.h" 

Currency::Currency(std::string name) throw(NameAlreadyTakenException) { 
    this->setName(name); 
    this->id = boost::uuids::random_generator()(); 
} 

Currency::Currency(const Currency& orig) { 

} 

Currency::~Currency() { 
} 

std::string Currency::getName() { 
    return this->name; 
} 

void Currency::setName(std::string name) throw(NameAlreadyTakenException) { 
    this->name = name; 
} 

我試圖使Currency通過實施由答案給予兩項建議重點兼容:C++ unordered_map using a custom class type as the key。正如你所看到的,我已經覆蓋了operator ==以及提供了一個自定義的hasher以及專門的模板。

儘管如此,關鍵似乎失去了價值。由此我的意思是雙打,浮動和整數變成0,字符串變成空字符串。當然,它會導致其他問題與其他任何我用作價值的問題。例如:

Currency dollar("Dollar") 
std::unordered_map<Currency,int,Currency::currencyHasher> currenMap; 
currenMap[dollar]=1337; 
std::cout<<currenMap[dollar]<<"\n"; 

這在控制檯輸出爲0 利用模板專業化不起作用或者:

std::unordered_map<Currency,int> currenMap; 
currenMap[dollar]=1337; 
std::cout<<currenMap[dollar]<<"\n"; 

產生一個0,以及...

CurrencyNameable的子類可能導致問題嗎?我使用boost :: uuid作爲散列(利用boost::hash<boost::uuids::uuid>將id轉換爲size_t)我不確定我錯過了什麼,我感謝您的幫助。

+0

Cue:http://stackoverflow.com/questions/10334688/how-dangerous-is-it-to-compare-floatingpoint-values/10335601#10335601 – sehe 2014-10-28 22:00:55

+0

@sehe我明白,平等不應該用於漂浮和雙打。但據我所知,我沒有使用平等的浮動和雙打。除非boost :: uuids由它們代表。 – Kammeot 2014-10-28 22:04:57

+1

同意。我剛看到「貨幣」後就回復了預兆:)你已經有了答案。這裏是獨立的:http://coliru.stacked-crooked.com/a/50e9f64070a7bafc – sehe 2014-10-28 22:14:29

回答

2

的問題是與拷貝構造函數:

Currency::Currency(const Currency& orig) { 

} 

當您複製Currency,你會得到一個缺省構造id。當您將Currency插入到地圖中時,它將被複制,並且該副本將具有與原始ID不同的ID。因此:

currenMap[dollar]=1337; 

{Currency(), 1337}有效地添加到地圖中。所以當你在查找帶有dollar創建的id時,它不會在那裏。並不是價值被「清零」......這是你得到一個默認構造的價值。

修復你的拷貝構造函數應該可以解決這個問題。

+0

'Currency(const Currency&orig)= default;虛擬〜貨幣()=默認;'看起來沒問題。 RuleOfZero – sehe 2014-10-28 22:11:33

+0

謝謝我通過將複製構造函數設置爲默認值來解決了我的問題。 '貨幣(const貨幣&orig)=默認;' – Kammeot 2014-10-28 22:23:06

相關問題