Сравнение двух экземпляров класса, не имеющих членов в качестве уникальных идентификаторов - PullRequest
0 голосов
/ 07 апреля 2019

Рассмотрим два класса Node и Edge, представляющие узлы и ребра мультиграфа соответственно (см. Мой код MWE ниже). Мое намерение состоит в том, чтобы использовать три unordered_map s:

(а) от Node переменных до Edge данных,

(b) от Edge переменных до Node данных и

(c) от Node пар до double переменных.

Я пытался написать bool operator==() функции для Node* и Edge* и хеш-функции для Node*, Edge* и pair<Node*,Node*>.

Моя первая проблема связана с функцией bool operator==() Edge. Хотя метки Node s, безусловно, уникальны, эта функция bool operator==() не подходит для нескольких ребер, имеющих одинаковые start s и end s (). Есть ли шанс построить правильную функцию bool operator==(), используя, , например, , адрес памяти Edge s?

Второй вопрос заключается в том, приводят ли эти функции к сохранению только различных Node/Edge/pair<Node,Node> объектов, если предполагается только простые ребра.

Итак, мой MWE выглядит следующим образом:

#include<string>
#include<vector>
#include<utility>
#include<unordered_map>
#include<iostream>
#include <bits/stdc++.h> 

using namespace std;


class Node
{
   public:
      Node(){};
      string label;
      bool operator==(const Node* other) const
      {return label == other->label;};
};

class Edge
{
   public:
      Edge(){};
      Node *start, *end;
      double weight;
      bool operator==(const Edge* other) const
      {return start->label == other->start->label && 
       end->label == other->end->label;};
      //{return this == *other;}
};

namespace std
{
   template <>
   struct hash<Node*>
   {
      size_t operator()(const Node* node) const
      {return hash<string>()(node->label);}
   };

   template <>
   struct hash<Edge*>
   {
      size_t operator()(const Edge* edge) const
      {
         auto hash1 = hash<Node*>()(edge->start);
         auto hash2 = hash<Node*>()(edge->end);
         return hash1 ^ hash2; 
      }
   };

   template <>
   struct hash<pair<Node*,Node*>>
   {
      size_t operator()(const pair<Node*, Node*>& p) const
      { 
          auto hash1 = hash<Node*>()(p.first); 
          auto hash2 = hash<Node*>()(p.second);
          return hash1 ^ hash2; 
      } 
   };
}; 

int main()
{
   Edge* edge;
   Node* node;

   unordered_map<Node*,Edge> n2e;
   unordered_map<Edge*,Node> e2n;
   unordered_map<pair<Node*,Node*>,double> np2w;

   edge = new Edge();
   edge->weight = 1.0;
   edge->start = new Node();
   edge->start->label = "A";
   edge->end = new Node();
   edge->end->label = "B";

   n2e[edge->start] = *edge;
   e2n[edge] = *(edge->start);
   np2w[make_pair(edge->start, edge->end)] = edge->weight;

   edge = &n2e[edge->start];
   node = &e2n[edge];

   return 0;
}

1 Ответ

0 голосов
/ 07 апреля 2019

Вы в основном определяете operator==(const Edge&, const Edge*),
, тогда как вам потребуется operator==(const Edge*, const Edge*), но последнее не может быть определено.

Вы должны написать класс, который определяет operator()(const Edge*, const Edge*) const и предоставить его в std::unordered_map.

struct MyEdgeComp
{
    bool operator()(const Edge* lhs, const Edge* rhs) const {
        return *lhs == *rhs; // Assuming you implement it
    }
};

std::unordered_map<Edge*, Node, std::hash<Edge*>, MyEdgeComp> e2n;
...