具有自定义密钥类型的STL无序映射

STL unordered map with custom key type

本文关键字:STL 无序 映射 类型 自定义 密钥      更新时间:2023-10-16

我有一些与图相关的C++代码,它们使用std::map结构。我不需要对元素进行严格排序,因此我希望切换到std::unordered_map结构。

代码的相关部分如下:

typedef unsigned size_type;
struct internal_edge{
 size_type node1_uid;
 size_type node2_uid;
};
std::map<size_type, internal_edge> edges_;

当我切换到std::unordered_map时,编译器抱怨"类模板'unordered_map'的模板参数太少"。我试着放入一个默认的哈希器和比较器(编辑:感谢@rems4e的更正版本):

struct size_type_hash {
    std::size_t operator()(const size_type& k) const
    {
        return std::hash<size_type>()(k);
    }
};
struct size_type_equal {
    bool operator()(const size_type& lhs, const size_type& rhs) const
    {
        return lhs == rhs;
    }
};
std::unordered_map<size_type, internal_edge, size_type_hash, size_type_equal> edges_;

这仍然会产生相同的错误消息:

./Graph.hpp:384:9: error: too few template arguments for class template 'unordered_map'
   std::unordered_map<size_type, internal_edge, size_type_hash, size_type_equal> edges_;
        ^
/usr/bin/../lib/c++/v1/__hash_table:86:28: note: template is declared here
    class _LIBCPP_TYPE_VIS unordered_map;
                           ^
In file included from viewer.cpp:21:
./Graph.hpp:384:82: warning: private field 'edges_' is not used [-Wunused-private-field]
   std::unordered_map<size_type, internal_edge, size_type_hash, size_type_equal> edges_;

我的Makefile:

...
CXX := $(shell which clang++) -stdlib=libc++ -std=gnu++11
...

以及clang++:的输出

Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix

我有点被困在那里了,因为这是我第一次进入C++世界。关于如何使无序映射构造函数工作,有什么想法吗?

标准库头可以以未指定的方式相互包含,头也可以包含额外的声明,因此当您忘记包含头时会出现错误(如果有的话),这并不一定是您所期望的。

例如,在这里,您包含的一个标头包含libc++的<__hash_table>内部标头,该标头包含unordered_map前向声明。这个正向声明不包含默认的模板参数(它不能有默认参数,因为该语言的规则阻止您在同一范围内的两个声明中为模板参数提供默认参数,所以如果它这样做了,然后用户还包括<unordered_map>-它必须提供默认参数-编译器会抱怨),因此,当编译器看到您试图将unordered_map与默认参数一起使用时,它会抱怨您的模板参数太少,而不是unordered_map没有声明。

如果您实际传递了必要数量的模板参数,编译器可能会抱怨您试图实例化一个已声明但未定义的模板。

修复方法很简单:包括<unordered_map>unsigned也不需要自定义散列器或比较器,只需使用默认的散列器或比较器即可。

您的问题可能来自错误的复制和粘贴,因为您正试图从size_type变量(即typedefunsigned int)中获取firstsecond字段。

用这些函数替换您的散列函数,您的代码将编译:

struct size_type_hash {
    std::size_t operator()(const size_type& k) const
    {
        return std::hash<size_type>()(k);
    }
};
struct size_type_equal {
    bool operator()(const size_type& lhs, const size_type& rhs) const
    {
        return lhs == rhs;
    }
};

为了确保安全,不要忘记在文件中包含标题。