如何用自定义的哈希函数来使用unordered_set::find。

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

我创建了一个无序集合,并定义了哈希函数。

struct pair_hash
{
    template<typename Ta, typename Tb>
    std::size_t operator() (std::pair<Ta, Tb> const& pair) const
    {
        std::size_t h1 = std::hash<Ta>()(pair.first);
        std::size_t h2 = std::hash<Tb>()(pair.second);
        return h1 ^ h2;
    }
};

我可以用以下方法创建这个集合:

std::unordered_set<std::pair<Atom*, Atom*>, pair_hash> bonds;

我也可以用... 把值插入到集合中去

bonds.insert(bond);

这一切都很好,但是我在尝试寻找集合中的元素时遇到了问题。当我尝试使用:时,我得到了 "Term does not evaluate to a function taking 1 arguments "的错误信息。

std::pair<Atom*, Atom*> bond = std::make_pair(atom_a, atom_b);
if (bonds.find(bond) == bonds.end())
{
    //Unbonded
}
else
{
    //Bonded
}

如果有任何帮助,我将非常感激! 以下是我的代码,供参考。

#include <iostream>
#include <vector>
#include <unordered_set>
#include <fstream>
#include <string>
#include <sstream>
#include <utility>

struct Vector3
{
    float x;
    float y;
    float z;
    Vector3(float x, float y, float z) : 
        x(x),
        y(y),
        z(z) 
    {}
};

struct Atom
{
    int atomic_number;
    Vector3 position;
    Vector3 velocity;
    Atom(int atomic_number, Vector3 position, Vector3 velocity = Vector3(0.0f, 0.0f, 0.0f)) :
        atomic_number(atomic_number),
        position(position),
        velocity(velocity)
    {}
};

std::vector<std::string> SplitString(const std::string& str, char delim)
{
    std::vector<std::string> out;
    std::stringstream curr;
    for (char c : str)
    {
        if (c == delim)
        {
            out.emplace_back(curr.str());
            curr.str("");
        }
        else
        {
            curr << c;
        }
    }
    out.emplace_back(curr.str());
    return out;
}

struct pair_hash
{
    template<typename Ta, typename Tb>
    std::size_t operator() (std::pair<Ta, Tb> const& pair) const
    {
        std::size_t h1 = std::hash<Ta>()(pair.first);
        std::size_t h2 = std::hash<Tb>()(pair.second);
        return h1 ^ h2;
    }
};

void LoadEnvironment(const char* file_name, std::vector<Atom*>& particles, std::unordered_set<std::pair<Atom*, Atom*>, pair_hash>& bonds)
{
    std::ifstream file(file_name);
    std::stringstream ss;
    ss << file.rdbuf();
    std::string data = ss.str();
    std::vector<std::string> molecule_strings = SplitString(data, '|');
    for (const std::string& molecule_string : molecule_strings)
    {
        std::vector<std::string> molecule_attributes = SplitString(molecule_string, '#');
        std::string& atom_data = molecule_attributes[0];
        std::string& bond_data = molecule_attributes[1];
        std::vector<std::string> atom_strings = SplitString(atom_data, '/');
        std::vector<std::string> bond_strings = SplitString(bond_data, '/');
        std::vector<Atom*> molecule_atoms;
        std::vector<std::pair<Atom*, Atom*>> molecule_bonds;
        for (const std::string& atom_string : atom_strings)
        {
            std::vector<std::string> atom_value_strings = SplitString(atom_string, ',');
            std::vector<float> atom_values;
            for (const std::string& atom_value_string : atom_value_strings)
            {
                float value = stof(atom_value_string);
                atom_values.push_back(value);
            }
            int atomic_number = static_cast<int>(atom_values[0]);
            Vector3 position(atom_values[1], atom_values[2], atom_values[3]);
            Vector3 velocity(atom_values[4], atom_values[5], atom_values[6]);
            Atom* atom = new Atom(atomic_number, position, velocity);
            molecule_atoms.push_back(atom);
        }
        for (const std::string& bond_string : bond_strings)
        {
            std::vector<std::string> bond_atoms = SplitString(bond_string, ',');
            int atom_a_index = stoi(bond_atoms[0]);
            int atom_b_index = stoi(bond_atoms[1]);
            Atom* atom_a = molecule_atoms[atom_a_index];
            Atom* atom_b = molecule_atoms[atom_b_index];
            molecule_bonds.emplace_back(atom_a, atom_b);
        }
        for (Atom* atom : molecule_atoms)
        {
            particles.push_back(atom);
        }
        for (std::pair<Atom*, Atom*> bond : molecule_bonds)
        {
            bonds.insert(bond);
        }
    }
}

void TimeStep(std::vector<Atom*>& atoms, const std::unordered_set<std::pair<Atom*, Atom*>> bonds)
{
    for (Atom* atom_a : atoms)
    {
        for (Atom* atom_b : atoms)
        {
            if (atom_a == atom_b) continue;
            std::pair<Atom*, Atom*> bond = std::make_pair(atom_a, atom_b);
            if (bonds.find(bond) == bonds.end())
            {
                //Unbonded
            }
            else
            {
                //Bonded
            }
        }
    }
}

int main()
{
    std::vector<Atom*> particles;
    std::unordered_set<std::pair<Atom*, Atom*>, pair_hash> bonds;
    LoadEnvironment("simulation.txt", particles, bonds);
    return 0;
}
c++ hash hashmap set find
1个回答
1
投票

你忘了模板参数 pair_hash

void TimeStep(std::vector<Atom*>& atoms, const std::unordered_set<std::pair<Atom*, Atom*>> bonds)

应该是

void TimeStep(std::vector<Atom*>& atoms, const std::unordered_set<std::pair<Atom*, Atom*>, pair_hash> bonds)

没有它 std::hash 将会使用,这不是专门用于 std::pair,即 std::hash<std::pair<X, Y>> 不存在,从而导致错误。

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