无法在使用自定义运算符==()的c ++无序集合中找到用户定义的类型

问题描述 投票:0回答:3

问题陈述:遍历对象数组,并检查对象是否存在于unordered_set中。

目标:我可以在一个容器中容纳数千个对象,以检查它们在另一个容器中的数百万个对象中是否存在。我选择unordered_set是因为它不断发现复杂性和用于迭代的向量。我是新手,如果您有其他替代方法,我将不胜感激。

问题: unordered_set查找未按预期运行,或者我弄错了概念!

Main:

int main() {
  std::vector<std::unique_ptr<Block>> vertices;

  vertices.push_back(std::make_unique<Block>("mod1", "work"));
  vertices.push_back(std::make_unique<Block>("mod2", "work"));
  vertices.push_back(std::make_unique<Block>("mod3", "work"));

  std::unordered_set<std::unique_ptr<Block>> undefs;

  undefs.insert(std::make_unique<Block>("mod1", "work"));
  undefs.insert(std::make_unique<Block>("mod2", "work"));

  for(auto& vertex : vertices) {
    auto search = undefs.find(vertex);
    if(search != undefs.end()){
      std::cout << "Block: " << vertex->getName() << "\n";
    }
  }
}

块类重载:

bool Block::operator==(std::unique_ptr<Block>& block) const {
  return block->getName() == mName;
}

预期输出:

mod1

mod2

Block:

#pragma once

#include <string>
#include <memory>

using std::string;

class Block {
  private:
    string mName;
    string mLib;
  public:
    Block(string const& name, string const& lib);
    string getName() const;
    string getLib() const;
    bool operator==(std::unique_ptr<Block>& block) const;
};
c++ c++11 unique-ptr unordered-set
3个回答
2
投票

您正在尝试比较指针,而不是值。您需要为类Block指定哈希函数。

例如,如果要使用mName作为键,则代码如下:

class Block {
private:
    string mName;
    string mLib;
public:
    Block(string const& name, string const& lib)
    {
        mName = name;
        mLib = lib;
    }
    string getName() const {
        return mName;
    };
    string getLib() const {
        return mLib;
    }
    bool operator==(const Block & block) const;
};

template<> struct std::hash<Block> {
    std::size_t operator()(const Block & block) const noexcept {
        return std::hash<std::string>{}(block.getName());
    }
};

bool Block::operator==(const Block & block) const {
    return block.getName() == mName;
}

int main() {
    std::vector<Block> vertices;

    vertices.emplace_back(Block("mod1", "work"));
    vertices.emplace_back(Block("mod2", "work"));
    vertices.emplace_back(Block("mod3", "work"));

    std::unordered_set<Block> undefs;
    undefs.emplace(Block("mod1", "work"));
    undefs.emplace(Block("mod2", "work"));

    for (auto& vertex : vertices) {
        auto search = undefs.find(vertex);
        if (search != undefs.end()) {
            std::cout << "Block: " << vertex.getName() << "\n";
        }
    }
}

2
投票

unordered_set需要散列函数和比较函数。您正在使用std::unique_ptr的现有哈希和比较功能,这绝对不是您想要的。

我不建议尝试更改std::unique_ptr<Block>的行为,因为这将导致其他需要普通语义的指针的代码混乱。而是为Block添加普通的哈希和比较函数,并将自定义的散列和比较函数传递给unordered_set的构造函数。


0
投票

问题是您正在尝试比较不同的指针!我不知道使用unique_ptr <>的原因,但是这样做实际上是在尝试比较身份,而不是想要的状态。

所以您可以明白我的意思,假设第一个Block对象在内存中的位置100。那就是它的身份。因此,我们有一个对象1,其状态为“ mod1,工作”,其身份为100。然后,我们有一个对象2,其身份为150,但其状态与对象1相同,即“ mod1,工作”。

向量和unordered_set内部的所有内容都是指针,因此您具有存储位置。当将它们插入向量中时,您插入的位置为100。但是在unordered_set中,您插入的位置为150。它们的状态相同,但是find方法正在查找内存位置。

希望我的回答对您有所帮助。如果您在这里发现任何错误或有不同的想法,请告诉我。祝好运! :)

© www.soinside.com 2019 - 2024. All rights reserved.