Как использовать unordered_set :: find с пользовательской функцией ha sh - PullRequest
0 голосов
/ 05 мая 2020

Я создал неупорядоченный набор и определил функцию ha sh как:

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 не оценивает функцию, принимающую 1 аргумент» При попытке использовать:

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;
}

1 Ответ

1 голос
/ 05 мая 2020

Вы забыли параметр шаблона 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>> не существует, что вызывает ошибку.

...