无法创建以用户定义类为键的二维无序映射

Cannot create two-dimensional unordered_map with user-defined class as key

本文关键字:二维 映射 无序 创建 用户 定义      更新时间:2023-10-16

如标题所述,当使用以用户定义类为键的二维映射时,我很难让VC++编译器工作。这是我要申报的地图:

std::unordered_map<tag, std::map<tag, std::pair<bool, bool>>> transitRights;

下面是类标记的声明和std::hash函数的特殊化:

class tag
{
public:
    tag();
    tag(const char[3]);
    tag(const std::string&);
    void operator=(const tag&);
    const bool operator==(const tag&)const;
    operator const std::string()const;
    const char& getA()const { return a; }
    const char& getB()const { return b; }
    const char& getC()const { return c; }
private:
    char a, b, c;
};

namespace std
{
    template<> class hash<tag>
    {
    public:
        size_t operator()(const tag& _tag) const
        {
            return hash<char>()(_tag.getA()) ^ hash<char>()(_tag.getB()) ^ hash<char>()(_tag.getC());
        }
    };
};

当试图编译时,Visual Studio向我抛出了一堆神秘的错误消息:

1>C:Program Files (x86)Microsoft Visual Studio 12.0VCincludexmemory0(600): error C2664: 'std::pair<const _Kty,_Ty>::pair(const std::pair<const _Kty,_Ty> &)' : cannot convert argument 1 from 'const tag' to 'const std::pair<const _Kty,_Ty> &'
1>          with
1>          [
1>              _Kty=int
1>  ,            _Ty=std::pair<bool,bool>
1>          ]
1>          Reason: cannot convert from 'const tag' to 'const std::pair<const _Kty,_Ty>'
1>          with
1>          [
1>              _Kty=int
1>  ,            _Ty=std::pair<bool,bool>
1>          ]
1>          No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>          C:Program Files (x86)Microsoft Visual Studio 12.0VCincludexmemory0(723) : see reference to function template instantiation 'void std::allocator<_Other>::construct<_Objty,const tag&>(_Objty *,const tag &)' being compiled
1>          with
1>          [
1>              _Other=std::_Tree_node<std::pair<const int,std::pair<bool,bool>>,void *>
1>  ,            _Objty=std::pair<const int,std::pair<bool,bool>>
1>          ]
1>          C:Program Files (x86)Microsoft Visual Studio 12.0VCincludexmemory0(723) : see reference to function template instantiation 'void std::allocator<_Other>::construct<_Objty,const tag&>(_Objty *,const tag &)' being compiled
1>          with
1>          [
1>              _Other=std::_Tree_node<std::pair<const int,std::pair<bool,bool>>,void *>
1>  ,            _Objty=std::pair<const int,std::pair<bool,bool>>
1>          ]
1>          C:Program Files (x86)Microsoft Visual Studio 12.0VCincludexmemory0(872) : see reference to function template instantiation 'void std::allocator_traits<_Alloc>::construct<_Ty,const tag&>(std::allocator<_Other> &,_Objty *,const tag &)' being compiled
1>          with
1>          [
1>              _Alloc=std::allocator<std::_Tree_node<std::pair<const int,std::pair<bool,bool>>,void *>>
1>  ,            _Ty=std::pair<const int,std::pair<bool,bool>>
1>  ,            _Other=std::_Tree_node<std::pair<const int,std::pair<bool,bool>>,void *>
1>  ,            _Objty=std::pair<const int,std::pair<bool,bool>>
1>          ]
1>          C:Program Files (x86)Microsoft Visual Studio 12.0VCincludexmemory0(872) : see reference to function template instantiation 'void std::allocator_traits<_Alloc>::construct<_Ty,const tag&>(std::allocator<_Other> &,_Objty *,const tag &)' being compiled
1>          with
1>          [
1>              _Alloc=std::allocator<std::_Tree_node<std::pair<const int,std::pair<bool,bool>>,void *>>
1>  ,            _Ty=std::pair<const int,std::pair<bool,bool>>
1>  ,            _Other=std::_Tree_node<std::pair<const int,std::pair<bool,bool>>,void *>
1>  ,            _Objty=std::pair<const int,std::pair<bool,bool>>
1>          ]
1>          C:Program Files (x86)Microsoft Visual Studio 12.0VCincludextree(933) : see reference to function template instantiation 'void std::_Wrap_alloc<std::allocator<_Other>>::construct<_Ty,const tag&>(_Ty *,const tag &)' being compiled
1>          with
1>          [
1>              _Other=std::_Tree_node<std::pair<const int,std::pair<bool,bool>>,void *>
1>  ,            _Ty=std::pair<const int,std::pair<bool,bool>>
1>          ]
1>          C:Program Files (x86)Microsoft Visual Studio 12.0VCincludextree(933) : see reference to function template instantiation 'void std::_Wrap_alloc<std::allocator<_Other>>::construct<_Ty,const tag&>(_Ty *,const tag &)' being compiled
1>          with
1>          [
1>              _Other=std::_Tree_node<std::pair<const int,std::pair<bool,bool>>,void *>
1>  ,            _Ty=std::pair<const int,std::pair<bool,bool>>
1>          ]
1>          C:Program Files (x86)Microsoft Visual Studio 12.0VCincludextree(1176) : see reference to function template instantiation 'std::_Tree_node<std::pair<const _Kty,_Ty>,void *> *std::_Tree_buy<std::pair<const _Kty,_Ty>,std::allocator<std::pair<const _Kty,_Ty>>>::_Buynode<const tag&>(const tag &)' being compiled
1>          with
1>          [
1>              _Kty=int
1>  ,            _Ty=std::pair<bool,bool>
1>          ]
1>          C:Program Files (x86)Microsoft Visual Studio 12.0VCincludextree(1176) : see reference to function template instantiation 'std::_Tree_node<std::pair<const _Kty,_Ty>,void *> *std::_Tree_buy<std::pair<const _Kty,_Ty>,std::allocator<std::pair<const _Kty,_Ty>>>::_Buynode<const tag&>(const tag &)' being compiled
1>          with
1>          [
1>              _Kty=int
1>  ,            _Ty=std::pair<bool,bool>
1>          ]
1>          nation.cpp(600) : see reference to function template instantiation 'std::pair<std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<const _Kty,_Ty>>>>,bool> std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::emplace<const tag&>(const tag &)' being compiled
1>          with
1>          [
1>              _Kty=int
1>  ,            _Ty=std::pair<bool,bool>
1>  ,            _Pr=std::less<int>
1>  ,            _Alloc=std::allocator<std::pair<const int,std::pair<bool,bool>>>
1>          ]
1>          nation.cpp(600) : see reference to function template instantiation 'std::pair<std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<const _Kty,_Ty>>>>,bool> std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::emplace<const tag&>(const tag &)' being compiled
1>          with
1>          [
1>              _Kty=int
1>  ,            _Ty=std::pair<bool,bool>
1>  ,            _Pr=std::less<int>
1>  ,            _Alloc=std::allocator<std::pair<const int,std::pair<bool,bool>>>
1>          ]

任何对我在这里做错了什么的见解都会得到极大的同情。

问题是嵌套对象是std::map(而不是unordered_map),因此需要对tag进行小于的比较。

但是,您应该能够构建unordered_mapunordered_map

哈希必须是struct:

namespace std {
    template<> struct hash<tag> {
               ^^^^^^
    public:
        size_t operator()(const tag& _tag) const {
            return hash<char>()(_tag.getA()) ^ hash<char>()(_tag.getB()) ^ hash<char>()(_tag.getC());
        }
    };
};

编辑:

正如@6502正确提到的,您还必须定义一个小于operator<的,因为您还使用了一个带有密钥tagstd::map(以下示例):

bool operator<(tag const &t1, tag const &t2) {
  return t1.getA() < t2.getA();    
}

现场演示