繁体   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

我想使用unordered_map<std::pair<enum_class,other_enum_class>,std::uint8_t>来管理一些像素图格式。

这里的最小代码:

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

使用GCC,当我尝试实例化类时出错

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

有了Clang,我也有一个错误

错误:未定义模板'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:注意:在这里请求的函数模板特化'pair_hash :: operator()'实例化[...]

使用VS2013我没有错误,代码编译和执行。

我的代码中缺少什么?

g ++ - 5给出以下错误:

无效使用不完整类型struct std::hash<PNM>

无效使用不完整类型struct std::hash<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));
   }
};

}

或者你可以编写模板结构,它只适用于使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM