【问题标题】:C++ bool std::operator < error with map with key std::unordered_set<int,std::hash<int>>C++ bool std::operator < 带有键 std::unordered_set<int,std::hash<int>> 的映射出错
【发布时间】:2014-06-16 22:54:34
【问题描述】:

当我尝试在此地图中插入时:

std::map&lt;std::unordered_set&lt;int &gt;, std::pair&lt;float, std::pair&lt;float, float &gt;&gt; &gt;

我收到了这个错误

错误 C2784: 'bool std::operator &,const std::_Tree<_traits> &)' : 无法推断出模板参数 'const std::_Tree<_traits> &' 来自 'const std::unordered_set,std::equal_to<_kty>,std::allocator<_kty>>'

我的数据定义如下:

    struct Trans {
    int Item;
    float Prob;
    float W;
};
bool operator<(const Trans &a, const Trans &b)
    {
        return a.Item < b.Item;
    }
    bool operator==( Trans c,  Trans d) { return c.Item == d.Item; }


    struct MyHash {
        size_t operator()(const Trans& x) const { return std::hash<int>()(x.Item);  }
    };


std::vector<std::vector<Trans>> data;
std::map<std::unordered_set<int>, float> S1;
std::map<std::unordered_set<int >, std::pair<float, std::pair<float, float >> > S2;
std::map<std::unordered_set<int >, std::pair<float, std::pair<float, float >> > S3;

有问题的部分:

    do
        {

std::unordered_set<Trans, MyHash> KS(data[i].begin(), data[i].begin() + k);
std::unordered_set<int > elem;

float esupp = 1;
float Weight = 0;
float Wesupp = 1;
    for (auto const &iter : KS)
        {
          elem.insert(iter.Item);
           esupp *= iter.Prob;
          Weight += iter.W;
        }
        Weight = Weight / k;


        /*
        some code, and until here I didn't get any problem
        */

            **// This the area that has the problem** 

    S1[elem] = std::move(S1[elem] + esupp);
    Wesupp = Weight * S1[elem];
    S2[elem].first = std::move(S2[elem].first + esupp);
    S2[elem].second = std::make_pair(elem, Wesupp);
  } while (next_combination(data[i].begin(), data[i].begin() + k, data[i].end()));

【问题讨论】:

  • 出现错误的实际行是什么?
  • 除此之外,这条线看起来不正确:S2[elem].second = std::make_pair(elem, Wesupp);
  • 我会认真重新考虑数据结构设计...unordered_set 作为键? std::pair&lt;float, std::pair&lt;float, float&gt;&gt;? (至少使用std::tuplestd::array&lt;float, 3&gt;
  • @ben 从 `S1[elem] = std::move(S1[elem] + esupp)` 到 `S2[elem].second = std::make_pair(elem, Wesupp) 的每一行;` 导致错误
  • @marco-a 在容器 S2 我想插入带有三个浮点值的 unordered_set elem。循环中的每一轮elem 都有unordered_set,如果它与上一轮相似,我将更新它们的三个浮点值,否则我将插入新的unordered_set 及其三个浮点值。

标签: c++ unordered-set


【解决方案1】:

除非提供了比较器,否则 std::map 期望其密钥实现运算符 &lt;

您的密钥类型std::unordered_set 没有实现“小于”。

作为@T.C.提到,您可以使用std::set 而不是std::unordered_set

【讨论】:

  • 谢谢,但如果我用std::unordered_map 替换std::map,我会得到另一个错误,error C2338: The C++ Standard doesn't provide a hash for this type.
  • @Sandy 然后我会删除该建议。您的错误的原因仍然相同。 C++ 不支持。
  • std::set 确实有标准定义的operator &lt;()
  • 谢谢大家,我需要使用std::unordered_set 而不是std::set 因为,我使用哈希函数来检查KS 是否是存储在S2', I have file of 100k lines, each line has different size, and I used 中的任何先前集合的超集next_combination` 用于生成KS,我在比较部分使用散列来减少时间,而不是使用STL includes()
  • @Sandy 你真的用std::set / std::includes 测量了速度吗?在谈论性能时,总是衡量。
【解决方案2】:

正如 Drew Dormann 指出的那样,您当前的错误是由 std::unordered_set 缺少 operator &lt; 引起的。

不过,std::set 确实有一个重载的operator &lt;,所以你可以使用它。

不过,您的代码的问题比这更严重。例如:

S1[elem] = std::move(S1[elem] + esupp);

您正在分配一个float。使用std::move 绝对没有意义,尤其是S1[elem] + esupp 已经是一个右值。写这行的通常方式是S1[elem] += esupp;

S2[elem].first = std::move(S2[elem].first + esupp);

同样的问题。

S2[elem].second = std::make_pair(elem, Wesupp);

作业的 LHS 是 std::pair&lt;float, float&gt;; RHS 创建一个std::pair&lt;std::unordered_set&lt;int&gt;, float&gt;

正如我在 cmets 中提到的,std::pair&lt;float, std::pair&lt;float, float&gt;&gt; 只是糟糕的设计。它至少应该是std::tuple,或者更好的是std::array&lt;float, 3&gt;,或者更好的是一个简单的结构,可以清楚地说明三个浮点数中的每一个的实际含义。

此外,在地图中使用set&lt;int&gt;(无序或无序)作为键是一种相当奇怪的设计。您是否只想维护一个可以迭代的set&lt;int&gt;-3xfloat 配对列表,或者您真的希望能够使用set&lt;int&gt; 有效地索引?如果您不需要高效的索引,只需使用成对的向量而不是地图。

【讨论】:

猜你喜欢
  • 2015-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-21
  • 1970-01-01
相关资源
最近更新 更多