带有自定义键的C ++ unordered_map导致空值

时间:2014-10-28 21:51:10

标签: c++ boost unordered-map

我使用的std::unordered_map密钥为Currency,价值为double的货币价格。 Currency是我制作的自定义类。这是我尝试过的一个版本:

#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。正如您所看到的,我已经覆盖了运算符==以及提供自定义哈希以及专门化模板。

尽管如此,关键似乎正在失去价值。我的意思是双打,浮点数和整数变成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)我不确定我缺少什么,谢谢你的帮助。< / p>

1 个答案:

答案 0 :(得分:2)

问题在于复制构造函数:

Currency::Currency(const Currency& orig) {

}

复制Currency时,您会获得默认构造的id。当您将Currency插入地图时,它会被复制,并且该副本的ID将与原始ID不同。因此:

currenMap[dollar]=1337;

有效地将{Currency(), 1337}添加到地图中。因此,当您查找具有为dollar创建的任何ID的那个时,它就不会在那里。这并不意味着价值会被淘汰,而是因为你得到了一个默认构造的价值。

修复复制构造函数应解决问题。