0

I'm trying to delete an edge from edges_, which is stored in a Graph class Node struct as a std::set using std::shared_ptr<Edge>:

template <typename N, typename E> class Graph {

    private:
        struct Node;
        struct Edge;

        struct Node {
            N val_;
            int numEdges_;
            int numIncomingEdges_;
            std::set<std::shared_ptr<Edge>> edges_;
            std::set<std::shared_ptr<Edge>> incomingEdges_;
            Node() {}
            Node(const N x) : val_{x} { numEdges_=0; }
            void printNode(N n);
            ~Node();
            void update();
        };

        struct Edge {
            std::weak_ptr<Node> orig;
            std::weak_ptr<Node> dest;
            E val_;
            Edge(std::shared_ptr<Node> o, std::shared_ptr<Node> d, E x);
            Edge() {};
            void printEdge();
            ~Edge();
        };

The following code is me trying to delete an edge from edges_, but first I need to find the edge from edges_ before I can use the erase() method for the std::set on it. However, the variable findEdge is equal to edges_.end(), as the given edge was not found in the set based on my if-else check ("cannot find edge in edges_!!" was printed). To find an element, std::set uses a Compare object whose type is defined via the second template parameter which I didn't specify, thus it's defaulting to std::less<std::shared_ptr<Edge>> which in turn calls the operator< of the shared pointer, which does not compare the objects but only the pointers. Therefore, if the pointers used for inserting and searching are not pointing to exactly the same (as in identical, not only "equal") object, it does not actually find the edge successfully.

            auto findEdge = findLinkingNode1->second->edges_.find(edge);
            // if can find edge in edges_
            if (findEdge != findLinkingNode1->second->edges_.end()) {
                std::cout << "can find edge in edges_ so erasing it!" << std::endl;
            findLinkingNode1->second->edges_.erase(findEdge);
            } else {
                std::cout << "cannot find edge in edges_!!" << std::endl;
            }

How an edge was inserted into edges_ is as follows, where the edge was made into a shared_ptr<Edge> to put into the std::set:

findOrig->second->edges_.insert(std::make_shared<Edge>(Edge (findOrig->second, findDest->second, val) ));

How do I implement a custom compare class for my set edges_ that compares the actual Edge objects, so findEdge can actually find the actual edge object needed?

iteong
  • 715
  • 3
  • 10
  • 26
  • There does not appear to be anything wrong with your logic. Since the actual pointers are being compared, if the pointers are not the same, they must not be pointing to the same edge object. Q.E.D. – Sam Varshavchik Sep 18 '16 at 01:38
  • How come it cannot find the edge though? – iteong Sep 18 '16 at 01:42
  • Because it's not there. It a pointer to some other edge, other than the one in the set. – Sam Varshavchik Sep 18 '16 at 01:44
  • Nope, I did the following check of the val_ of the 2 different edges for the deletable node and its linking node and they are the same for one in the set. But I can't seem to erase it from the set. – iteong Sep 18 '16 at 02:11
  • for (auto edgeLink: findLinkingNode1->second->edges_) { std::cout << "An outgoing edge in origin node " << nodeVal1 << " of incoming edge to deleted node (outgoing edge " << edgeLink->val_ << ")" << std::endl; //auto findEdge = findLinkingNode1->second->edges_.find(edge); std::cout << "edgeLink->val_ is: " << edgeLink->val_ << " and edge->val_ is: " << edge->val_ << std::endl; if (edgeLink->val_ == edge->val_) { std::cout << "they are the same, so try to erase...." << std::endl; findLinkingNode1->second->edges_.erase(edge); } } – iteong Sep 18 '16 at 02:11
  • I commented out findEdge for this revised code coz it wasn't working to see if the edges were the same, so I used the val_ to check if they are the same instead. It's just that I don't know how come it cannot erase it from the set even though they have the same weight value. When I do use findEdge, and put it into edges_erase.(findEdge), it doesn't work and will have a "pointer being freed was not allocated" error. – iteong Sep 18 '16 at 02:15
  • Could it be that the internal representation of the edges for the deletable node and the link node is different for the origin and destination? That is why it cannot find the node even though they have the same val_? – iteong Sep 18 '16 at 02:20

0 Answers0