0

I'm trying to learn how maps work and how to implement them for Graphs. I keep getting the error above. I assume it's because the '<' is taking less than data it is not suppose to.

using namespace std;


struct Node {
    string name;
    int val;

    Node(string n) {
        name = n;
        val = 0;
    }

};

struct AdjList {

    map<Node, list<Node*>> adj;
    map<Node, list<Node*>>::iterator it;
    int type; 

    AdjList(int a) {
        type = a;
    }


    void add(Node temp) {
        it = adj.end();
        list <Node*> hi;
        adj.insert(pair <Node, list <Node*>>(temp, hi));
    }

    void connect(Node *a, Node *b) {
        adj.find(*a)->second.push_back(b);
        if (type == 1) {
            adj.find(*b)->second.push_back(a);
        }
    }

    void connect(Node *a, vector <Node*> b) {
        for (int i = 0; i < b.size(); i++) {
            connect(a, b[i]);
        }
    }
};
lyph
  • 17
  • 1
  • 1
  • 8

1 Answers1

4

It's erroring out because you didn't define operator< for your Node class (as a method or as a non-member function).

Take a look here for operator overloading; since map stores the keys in sorted order, they must implement operator< to be used.

An example implementation might be to sort by val then by name, in which case you'd implement as:

#include <tuple>

inline bool operator==(const Node& lhs, const Node& rhs){
    return lhs.val == rhs.val && lhs.name == lhs.name;
}
inline bool operator!=(const Node& lhs, const Node& rhs){return !operator==(lhs,rhs);}
inline bool operator< (const Node& lhs, const Node& rhs){
    // std::tuple's lexicographic ordering does all the actual work for you
    // and using std::tie means no actual copies are made
    return std::tie(lhs.val, lhs.name) < std::tie(rhs.val, rhs.name);
}
inline bool operator> (const Node& lhs, const Node& rhs){return  operator< (rhs,lhs);}
inline bool operator<=(const Node& lhs, const Node& rhs){return !operator> (lhs,rhs);}
inline bool operator>=(const Node& lhs, const Node& rhs){return !operator< (lhs,rhs);}
Community
  • 1
  • 1
ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • The only operator you *must* define to use your class as a `std::map` key is `<` -- the others might be useful to you but won't be used by `std::map` – Chris Dodd Nov 04 '16 at 00:49
  • @ChrisDodd: Yar. I implemented all the others because not doing so makes your class harder for other programmers to use and it's good practice to implement all of them, but like I said, `map` requires `operator<` (I just didn't make it clear it _only_ cared about `operator<`). Any opportunity to illustrate how easy it is to define the other four operations in terms of `operator==` and `operator<` should always be taken. :-) – ShadowRanger Nov 04 '16 at 00:51
  • I don't quite get how you "sort" objects. Would it be sorted based on address of the object? Like if in this case Node was empty how would the "<" operator be implemented? – lyph Nov 05 '16 at 02:18
  • @lyph: Why would you be putting empty `Node`s in a `map`? The sorting is whatever you define it to be, that's the whole point. My example sorted by `val` then by `name`, but you could redefine it. – ShadowRanger Nov 05 '16 at 02:24
  • @ShadowRanger I was just wondering for conceptual sake. Oh, so if both vals equal each other it would compare strings? – lyph Nov 05 '16 at 02:39
  • @lyph: Yup. `std::tuple` compares lexicographically. So for a `<`, it basically checks, from left to right, until it finds a pair that aren't equal, then returns `true` if the left is `<` the right for the first unequal pair. – ShadowRanger Nov 05 '16 at 02:41