当使用向量作为键时,C ++ unordered_map失败 [英] C++ unordered_map fail when used with a vector as key

查看:306
本文介绍了当使用向量作为键时,C ++ unordered_map失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景:我来自Java世界,我对C ++或Qt很新。



为了使用unordered_map,我写了以下简单的程序:

  #include< QtCore / QCoreApplication> 
#include< QtCore>
#include< iostream>
#include< stdio.h>
#include< string>
#include< unordered_map>

使用std :: string;
using std :: cout;
using std :: endl;
typedef std :: vector< float> floatVector;

int main(int argc,char * argv []){
QCoreApplication a(argc,argv);

floatVector c(10);
floatVector b(10);

for(int i = 0; i <10; i ++){
c [i] = i + 1;
b [i] = i * 2;
}

std :: unordered_map< floatVector,int>地图;

map [b] = 135;
map [c] = 40;
map [c] = 32;

std :: cout<< b - ><< map [b]< std :: endl;
std :: cout<< c - ><< map [c]< std :: endl;
std :: cout<< 包含? - ><< map.size()<< std :: endl;

return a.exec();不幸的是,我遇到了下面的错误,这是不是鼓舞人心的。


: - 1:错误:collect2:ld退回1退出状态




有关问题原因的任何想法吗?



提前感谢。

解决方案

§23.2.5第3段说:


每个无序关联容器由 Key 通过满足哈希要求(17.6。)的函数对象类型 Hash 3.4),并且作为 Key 的参数值的散列函数,以及由二元谓词 Pred 键的值的等价关系。


使用向量< float> 作为,并且不提供显式哈希和等价谓词类型意味着默认 std :: hash<将使用向量< float>> std :: equal_to< vector< float>>

等价关系的 std :: equal_to 很好,因为有一个操作符 == 为向量,这是 std :: equal_to 使用。



但是,没有 std :: hash< vector< float>> 专业化,这可能是什么链接器错误你没有告诉我们说。



编写这样一个哈希的简单方法是使用 boost :: hash_range

  template< typename Container> //我们可以为任何容器做这个泛型[1] 
struct container_hash {
std :: size_t operator()(Container const& c)const {
return boost :: hash_range .begin(),c.end());
}
};

然后您可以使用:

  std :: unordered_map< floatVector,int,container_hash< floaVector>>地图; 

当然,如果你在地图中需要不同的等式语义,你需要定义哈希和等价关系






1。但是,避免这种哈希无序容器,因为不同的顺序将产生不同的哈希,而无序的容器中的顺序不能保证。


Background: I am comming from the Java world and I am fairly new to C++ or Qt.

In order to play with unordered_map, I have written the following simple program:

#include <QtCore/QCoreApplication>
#include <QtCore>
#include <iostream>
#include <stdio.h>
#include <string>
#include <unordered_map>

using std::string;
using std::cout;
using std::endl;
typedef std::vector<float> floatVector;

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    floatVector c(10);
    floatVector b(10);

    for (int i = 0; i < 10; i++) {
        c[i] = i + 1;
        b[i] = i * 2;
    }

    std::unordered_map<floatVector, int> map;

    map[b] = 135;
    map[c] = 40;
    map[c] = 32;

    std::cout << "b -> " << map[b] << std::endl;
    std::cout << "c -> " << map[c] << std::endl;
    std::cout << "Contains? -> " << map.size() << std::endl;

    return a.exec();
}

Unfortunately, I am running into the folowing error which isn't inspiring. There is not even a line number.

:-1: error: collect2: ld returned 1 exit status

Any idea of the origin of the problem?

Thanks in advance.

解决方案

§23.2.5, paragraph 3, says:

Each unordered associative container is parameterized by Key, by a function object type Hash that meets the Hash requirements (17.6.3.4) and acts as a hash function for argument values of type Key, and by a binary predicate Pred that induces an equivalence relation on values of type Key.

Using vector<float> as Key and not providing explicit hash and equivalence predicate types means the default std::hash<vector<float>> and std::equal_to<vector<float>> will be used.

The std::equal_to for the equivalence relation is fine, because there is an operator == for vectors, and that's what std::equal_to uses.

There is however, no std::hash<vector<float>> specialization, and that's probably what the linker error you didn't show us says. You need to provide your own hasher for this to work.

An easy way of writing such an hasher is to use boost::hash_range:

template <typename Container> // we can make this generic for any container [1]
struct container_hash {
    std::size_t operator()(Container const& c) const {
        return boost::hash_range(c.begin(), c.end());
    }
};

Then you can use:

std::unordered_map<floatVector, int, container_hash<floaVector>> map;

Of course, if you need different equality semantics in the map you need to define the hash and equivalence relation appropriately.


1. However, avoid this for hashing unordered containers, as different orders will produce different hashes, and the order in unordered container is not guaranteed.

这篇关于当使用向量作为键时,C ++ unordered_map失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆