简体   繁体   English

使用带有std :: pair枚举类的unordered_map作为键的不完整类型struct std :: hash无效

[英]Invalid use of incomplete type struct std::hash with unordered_map with std::pair of enum class as key

I want to use a unordered_map<std::pair<enum_class,other_enum_class>,std::uint8_t> for managing some pixelmap formats. 我想使用unordered_map<std::pair<enum_class,other_enum_class>,std::uint8_t>来管理一些像素图格式。

Here the minimal code : 这里的最小代码:

#include <unordered_map>
#include <utility>
#include <cstdint> 
#include <iostream>
#include <functional>

enum class PNM : std::uint8_t { PBM, PGM, PPM };
enum class Format : bool      { BIN, ASCII };

struct pair_hash {
public:
    template <typename T, typename U>
    std::size_t operator()(const std::pair<T, U> &x) const { 
        return std::hash<T>()(x.first) ^ std::hash<U>()(x.second); 
    }
};

int main(){

    std::unordered_map<std::pair<PNM, Format>, std::uint8_t, pair_hash> k_magic_number ({
        { { PNM::PBM, Format::BIN   }, 1 }, { { PNM::PGM, Format::BIN   }, 2 }, { { PNM::PPM, Format::BIN   }, 3 },
        { { PNM::PBM, Format::ASCII }, 4 }, { { PNM::PGM, Format::ASCII }, 5 }, { { PNM::PPM, Format::ASCII }, 6 }
    });

    std::cout << k_magic_number[std::make_pair<PNM, Format>(PNM::PBM, Format::BIN)];
}

With GCC I have an error when I try to instantiate the class : 使用GCC,当我尝试实例化类时出错

main.cpp:14:24: error: invalid use of incomplete type 'struct std::hash' main.cpp:14:24:错误:无效使用不完整类型'struct std :: hash'
return std::hash()(x.first) ^ std::hash()(x.second); return std :: hash()(x.first)^ std :: hash()(x.second);
In file included from 在包含的文件中
/usr/local/include/c++/5.2.0/bits/basic_string.h:5469:0, /usr/local/include/c++/5.2.0/bits/basic_string.h:5469:0,
from /usr/local/include/c++/5.2.0/string:52, 来自/usr/local/include/c++/5.2.0/string:52,
[...] [...]

With Clang I also have an error : 有了Clang,我也有一个错误

error: implicit instantiation of undefined template 'std::hash' return std::hash()(x.first) ^ std::hash()(x.second); 错误:未定义模板'std :: hash'的隐式实例化返回std :: hash()(x.first)^ std :: hash()(x.second); /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/bits/hashtable_policy.h:1257:16: note: in instantiation of function template specialization 'pair_hash::operator()' requested here [...] /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/bits/hashtable_policy。 h:1257:16:注意:在这里请求的函数模板特化'pair_hash :: operator()'实例化[...]

With VS2013 I have no error and the code compile and executes. 使用VS2013我没有错误,代码编译和执行。

What is missing in my code ? 我的代码中缺少什么?

g++-5 gives following errors: g ++ - 5给出以下错误:

invalid use of incomplete type struct std::hash<PNM> 无效使用不完整类型struct std::hash<PNM>

invalid use of incomplete type struct std::hash<Format> 无效使用不完整类型struct std::hash<Format>

So, you should just specialize std::hash for PNM and Format . 所以,你应该专门为PNMFormat std::hash

namespace std {
template<>
struct hash<PNM>
{
   typedef PNR argument_type;
   typedef size_t result_type;

   result_type operator () (const argument_type& x) const
   {
      using type = typename std::underlying_type<argument_type>::type;
      return std::hash<type>()(static_cast<type>(x));
   }
};

template<>
struct hash<Format>
{
   typedef Format argument_type;
   typedef size_t result_type;       

   result_type operator () (const argument_type& x) const
   {
      using type = typename std::underlying_type<argument_type>::type;
      return std::hash<type>()(static_cast<type>(x));
   }
};

}

Or you can write template struct, that will works only for enums with use of SFINAE (not sure, that it's not UB by standard, since it's not specialization actually). 或者你可以编写模板结构,它只适用于使用SFINAE的enums (不确定,它不是标准的UB,因为它实际上不是专业化)。

namespace std
{

template<typename E>
struct hash
{
   typedef E argument_type;
   typedef size_t result_type;
   using sfinae = typename std::enable_if<std::is_enum<E>::value>::type;

   result_type operator() (const E& e) const
   {
      using base_t = typename std::underlying_type<E>::type;
      return std::hash<base_t>()(static_cast<base_t>(e));
   }
};

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 `std :: pair``second`具有&#39;unordered_map`树的不完整类型 - `std::pair` `second` has incomplete type with `unordered_map` tree 使用结构作为 std::unordered_map 的键 - Using A Struct As Key For std::unordered_map 如何直接使用key作为std :: unordered_map的哈希? - How to directly use key as hash for std::unordered_map? 使用std :: pair作为键创建std :: unordered_map - Creating an std::unordered_map with an std::pair as key 使用std :: pair作为std :: unordered_map中的键 - Using std::pair as key in std::unordered_map 如何将 std::unordered_map 与 std::pair 一起使用? - How to Use std::unordered_map with std::pair? std :: make_pair,std :: unordered_map以及键类型中的move构造函数的用法 - std::make_pair, std::unordered_map and usage of move constructor from key type unordered_map ::在VS2012中查找带有自定义哈希崩溃的关键std ::指针对 - unordered_map::find with key std::pair of pointers with custom hash crashes in VS2012 错误:无效使用不完整类型&#39;struct std :: hash &lt;&gt;&#39; - error: invalid use of incomplete type 'struct std::hash<>' 为什么std :: map接受std :: pair作为键,但std :: unordered_map不接受? - Why does std::map accept a std::pair as key, but std::unordered_map does not?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM