Reputation:
I'm very new to C++ and I'm trying to use a user-defined type, a struct, with a container class, which in this case is a Set.
I know that to store elements of user-defined type, which can't be compared using the built-in relational operators, I'll need to write a comparison callback function and pass it to the Set constructor. I can't figure out what the syntax for this is, though.
I have this defined in my .cpp file:
Set<struct> included;
And then this is defined in a header file:
struct pointT {
int row;
int col;
bool operator==(PointT p1, PointT, p2) {
return p1.x == p2.x && p1.y == p2.y;
}
};
Is this all I need to do, or am I missing some big here, as the code doesn't seem to compile as the type is not recognized?
I've looked on this site for similar answers, but I can't find anything specific and clear to this situation. Any help would be appreciated.
Upvotes: 1
Views: 870
Reputation: 427
You can try something like this:
#include <iostream>
#include <set>
namespace point {
struct PointT {
int x;
int y;
};
bool operator==(const PointT& p1, const PointT& p2) {
return p1.x < p2.x || (p1.x == p2.x && p1.y < p2.y);
}
bool operator<(const PointT& p1, const PointT& p2) {
return p1.x < p2.x && p1.y < p2.y;
}
bool operator<=(const PointT& p1, const PointT& p2) {
return p1 < p2 || p1 == p2;
}
bool operator>(const PointT& p1, const PointT& p2) {
return p2 < p1;
}
bool operator>=(const PointT& p1, const PointT& p2) {
return p2 < p1 || p1 == p2;
}
}
int main()
{
using namespace point;
std::set<PointT> s{ { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 5 }, { 1, 2 } };
for (const auto& e : s) std::cout << "(" << e.x << "," << e.y << ")" << std::endl;
return 0;
}
Upvotes: 0
Reputation: 254431
First, choose a name for the class; you're calling it variously pointT
, PointT
, and struct
(which isn't even a valid name). I'll just call it point
, since I don't like weird decorations on names.
Then you need to decide on the member names: are they row
and col
or x
and y
? I'll choose the first.
To store it in std::set
(or, in general, to use it as a key in standard associative containers), you need operator<
, not operator==
, since associative keys are ordered. This can either be a member function with one parameter (this
being the left-hand operand, and the parameter being the right-hand):
struct point {
int row;
int col;
bool operator<(point const & rhs) {
return std::tie(row, col) < std::tie(rhs.row, rhs.col);
}
};
or a non-member with two parameters:
bool operator<(point const & lhs, point const & rhs) {
return std::tie(lhs.row, lhs.col) < std::tie(rhs.row, rhs.col);
}
Note that my example implementation needs the C++11 <tuple>
header, and assumes you want a lexicographical ordering (or don't particularly care about the ordering). If you're stuck in the past, then you'll need to write it yourself; something like:
bool operator<(point const & lhs, point const & rhs) {
if (lhs.row < rhs.row) return true;
if (rhs.row < lhs.row) return false;
return lhs.col < rhs.col;
}
If your Set
doesn't behave like a standard associative container, then it may have other requirements; but I can't guess what they might be. You'll have to consult that class's documentation.
Upvotes: 2