错误:无效使用不完整类型&#st; struct std :: hash<>'

时间:2018-01-17 05:53:16

标签: c++ hash hashmap unordered-map

如何为key创建一个哈希函数,作为在unordered_map中使用的字符串和枚举对?

我有以下这对无序地图的关键如何创建一个哈希,以便在unordered_map中使用?

enum Color {
Red,
Green
};

typedef std::pair <std::string, Color>

我尝试了以下内容但遇到了编译错误

struct EnumClassHash
{
    template <typename T>
    std::size_t operator()(T t) const
    {
        return static_cast<std::size_t>(t);
    }
};
size_t hash( const PairType & pair ) {
    return std::hash<std::string>()(pair.first) ^
           std::hash<EnumClassHash>()(pair.second);
}

typedef std::unordered_map<PairType, std::string>, 
    std::function<decltype(hash)>> ColorMapType;
error: invalid use of incomplete type 'struct std::hash<EnumClassHash>'
            std::hash<EnumClassHash>()(pairType.second);

以下不起作用

size_t hash( const PairType & pairType ) {
    return std::hash<std::string>()(pairType.first) ^
           std::hash<Color>()(pairType.second);
}


 typedef std::unordered_map<PairType, std::string, \
    std::function<decltype(hash)>> ColorMapType;

ColorMapType colorMap(100, hash);
error: invalid use of incomplete type 'struct std::hash<Color>'
            std::hash<Color>()(pair.second

);

PS Pardon我的格式化。我丢失了我的Gmail密码,只能从一个小屏幕的移动应用程序发布。

1 个答案:

答案 0 :(得分:2)

  • 当您声明struct EnumClassHash时,这是它自己的事情,而不是std::hash的专业化。
  • 当您撰写std::hash<EnumClassHash>()(pair.second)时,模板专精std::hash<EnumClassHash>根本就不存在。

你可以:

  • 声明struct EnumClassHash,并使用EnumClassHash
  • std::hash专门化为std::hash<Color>,并使用std::hash<Color>
  • 同时做到,

但从不混合和匹配每种方法的一部分,这没有任何意义。

此外,要使用std::pair<std::string, Color>作为std::unordered_map的关键类型,std::hash<Color>EnumClassHash都不重要。重要的是std::hash<std::pair<std::string, Color>>或您自己的哈希std::pair<std::string, Color>

这是您可以遵循的食谱。

要使用std::pair<std::string, Color>作为键类型,您需要自己专门设置std::hash<std::pair<std::string, Color>>

template <>
struct std::hash<std::pair<std::string, Color>>
{
    std::size_t operator()(const std::pair<std::string, Color>& p) const {
        return std::hash<std::string>()(p.first) ^ std::hash<Color>()(p.second);
    }
};

但在此之前,您需要首先专注std::hash<Color>,因为std::hash<std::pair<std::string, Color>>使用它。

template <>
struct std::hash<Color>
{
    std::size_t operator()(Color c) const {
        return static_cast<size_t>(c);
    }
};

然后,您可以使用std::unordered_map<std::pair<std::string, Color>, std::string>之类的内容。没有EnumClassHash参与。

如果你非常喜欢EnumClassHash,这是另一个方法。

您可以随意保留EnumClassHash

struct EnumClassHash
{
    template <typename T>
    std::size_t operator()(T t) const
    {
        return static_cast<std::size_t>(t);
    }
};

这一次,std::hash<Color>不存在。不要使用它。 (更不用说没有意义的std::hash<EnumClassHash>。)

因此,散列键类型的类应该使用EnumClassHash。 (再一次,不是std::hash<EnumClassHash>!)

struct PairHash {
    std::size_t operator()(const std::pair<std::string, Color>& p) const {
        return std::hash<std::string>()(p.first) ^ EnumClassHash()(p.second);
    }
};

现在,您可以使用std::unordered_map<std::pair<std::string, Color>, std::string, PairHash>