I noticed I can't directly compare two SDL_points:
SDL_Point a = {1, 2};
SDL_Point b = {1, 2};
if (a == b) std::cout << "a = b\n"; // Doesn't compile.
if (a.x == b.x && a.y == b.y) // I have to do this instead.
std::cout << "a = b\n";
I would like to overload the operator==, but since SDL_Point is part of SDL, I'm not sure how, because I may want to use the overloaded operator in many different classes of my game.
What's the normal way to do this?
Just have a utility or sdl_utility header that defines the operator inline:
inline bool operator==(SDL_Point const &a, SDL_Point const &b)
{
return a.x == b.x && a.y == b.y;
}
inline bool operator!=(SDL_Point const &a, SDL_Point const &b)
{
return !(a == b);
}
You will have to include this header in any source file that wants to use the operator.
Related
This question already has an answer here:
Efficient operator< with multiple members
(1 answer)
Closed 1 year ago.
I would like to use a struct with three integer members as a key. How can I overload the < operator. I understand that for two members it could be overloaded as:
bool operator < (const CacheKey& a, const CacheKey& b) {
return a.x < b.x || (a.x == b.x && a.y < b.y);
}
The generic solution is:
if (a.x != b.x) return a.x < b.x;
if (a.y != b.y) return a.y < b.y;
// ...
return false;
Or:
return std::tie(a.x, a.y) < std::tie(b.x, b.y);
(In this case, you might want to create a member function that returns the tied members, to be able to do something like a.tie() < b.tie() for all needed operators.)
Or, in C++20, you would add following to your class to automatically get all comparison operators including <:
auto operator<=>(const CacheKey &) const = default;
The most direct approach would be:
class Foo {
friend bool operator<(const Foo&, const Foo&);
int a, b, c;
}
bool operator<(const Foo& lhs, const Foo& rhs) {
return (lhs.a < rhs.a) ||
(lhs.a == rhs.a && lhs.b < rhs.b) ||
(lhs.a == rhs.a && lhs.b == rhs.b && lhs.c < rhs.c);
}
Hello to everyone who will find this post helpful. I had this custom class Position and I wanted to use it in std::map
class Position
{
public:
int x;
int y;
Position(const int &pos_x, const int &pos_y)
: x(pos_x), y(pos_y) {}
};
But i had error because it couldn't compare the classes to each other. So I created this comparison class:
class PosComparator
{
public:
bool operator()(const ConsoleRenderer::Position &A, const ConsoleRenderer::Position &B)
{
if (A.x < B.x)
return true;
else if (A.x == B.x && A.y < B.y)
return true;
return false;
}
};
But I got this this error:
static assertion failed: comparison object must be invocable as const
As the error implied, adding const at the end solves the problem:
class PosComparator
{
public:
bool operator()(const ConsoleRenderer::Position &A, const ConsoleRenderer::Position &B) const
{
if (A.x < B.x)
return true;
else if (A.x == B.x && A.y < B.y)
return true;
return false;
}
};
Or make it shorter by using std::tie, creating tuples which can be use to compare:
class PosComparator
{
public:
bool operator()(const ConsoleRenderer::Position &A, const ConsoleRenderer::Position &B) const
{
return std::tie(A.x, A.y) < std::tie(B.x, B.y);
}
};
I solved it with simply adding const at the end of the line.
class PosComparator
{
public:
bool operator()(const ConsoleRenderer::Position &A, const ConsoleRenderer::Position &B) const
{
if (A.x < B.x)
return true;
else if (A.x == B.x && A.y < B.y)
return true;
return false;
}
};
Hopefully this helped. :)
I have written a Point struct I am using to model the n-body problem. I have found it difficult to fully understand and implement the copy & swap idiom and adapting it to my needs, which are mainly speed. Am I doing this correctly? Would it be different in C++17?
#pragma once
#include <algorithm>
struct Point
{
double x, y, z;
explicit Point(double X = 0, double Y = 0, double Z = 0) : x(X), y(Y), z(Z) {}
void swap(Point&, Point&);
inline bool operator==(Point b) const { return (x == b.x && y == b.y && z == b.z); }
inline bool operator!=(Point b) const { return (x != b.x || y != b.y || z != b.z); }
Point& operator=(Point&);
Point& operator+(Point&) const;
Point& operator-(Point&) const;
inline double operator*(Point& b) const { return b.x*x + b.y*y + b.z*z; } // Dot product
Point& operator%(Point&) const; // % = Cross product
inline Point& operator+=(Point& b) { return *this = *this + b; }
inline Point& operator-=(Point& b) { return *this = *this - b; }
inline Point& operator%=(Point& b) { return *this = *this % b; }
Point& operator*(double) const;
Point& operator/(double) const;
inline Point& operator*=(double k) { return *this = *this * k; }
inline Point& operator/=(double k) { return *this = *this / k; }
};
std::ostream &operator<<(std::ostream &os, const Point& a) {
os << "(" << a.x << ", " << a.y << ", " << a.z << ")";
return os;
}
void Point::swap(Point& a, Point& b) {
std::swap(a.x, b.x);
std::swap(a.y, b.y);
std::swap(a.z, b.z);
}
Point& Point::operator=(Point& b) {
swap(*this, b);
return *this;
}
Point& Point::operator+(Point& b) const {
Point *p = new Point(x + b.x, y + b.y, z + b.z);
return *p;
}
Point& Point::operator-(Point& b) const {
Point *p = new Point(x - b.x, y - b.y, z - b.z);
return *p;
}
Point& Point::operator%(Point& b) const {
Point *p = new Point(
y*b.z - z*b.y,
z*b.x - x*b.z,
x*b.y - y*b.x
);
return *p;
}
Point& Point::operator*(double k) const {
Point *p = new Point(k*x, k*y, k*z);
return *p;
}
Point& Point::operator/(double k) const {
Point *p = new Point(x/k, y/k, z/k);
return *p;
}
The copy/swap-ideom actually copies and swap()s the values. Your "adaptation" merely swap()s. A correct use of the copy/swap-ideom would look, e.g., like this:
Point& Point::operator= (Point other) { // note: by value, i.e., already copied
this->swap(other);
return *this;
}
(of course, this also assumes that your swap() function is a member taking just one additional argument: there is already an object to swap with).
If speed is your primary concern, the copy/swap-ideom is probably not particular suitable for the case of Point: the copy operation is essentially trivial. Swapping values is quite reasonable compared to relatively involved operations like copying an array old by a std::vector where the swap operation just amounts to a few pointer swaps in addition to copying probably multiple values and some allocation operations. That is, your Point assignment is probably best off to just assign all members:
Point& Point::operator= (Point const& other) { // note: no copy...
this->x = other.x;
this->y = other.y;
this->z = other.z;
return *this;
}
As was pointed out in comments, you should also not allocate new Point objects with new: C++ isn't Java or C#! You can just create an object on the stack it doesn't need to come from the heap, e.g.:
Point Point::operator+ (Point const& other) const {
return Point(this->x + other.x, this->y + other.y, this->z + other.z);
}
In the following simple structs, p3 inherits from p2.
struct p2 {
double x, y;
p2(double x, double y) : x(x),y(y){}
bool operator ==(const p2& b) const{ return x == b.x && y == b.y; }
bool operator !=(const p2& b) const{ return !(*this == b); }
};
struct p3 : p2 {
double z;
p3(double x, double y, double z) : p2(x,y),z(z){}
bool operator ==(const p3& b) const{ return x == b.x && y == b.y && z == b.z; }
bool operator !=(const p3& b) const{ return !(*this == b); }
};
In the overloaded comparison operators for p3, how can I replace the x == b.x && y == b.y part with a call to the overloaded operator from the parent class?
Just use the scoping operator :: in the derived struct
So in your operator==() in struct p3 looks like this:
bool operator==(const p3& b) const {
return p2::operator==(b) && z == b.z;
}
bool operator==(const p3& b) const
{
return p2::operator==(b) && z == b.z;
// ~~~~~~~~~~~~~~~~^
}
I made operator for !=
PairXY operator != (PairXY a, PairXY b) {
PairXY res(a.x != b.x, a.y != b.y);
return res;
}
And i want to use it in this loop:
while (l.b!=l.a){}
But it gives me this error: could not convert 'operator!=(l.Line::b, l.Line::a)' to 'bool', i tried changing operator's PairXY to bool, but it stil didn't help.
bool operator != (PairXY a, PairXY b) { ... }
The return type should be bool:
bool operator != (const PairXY & a, const PairXY & b);
Also, better make the parameters const reference, as I shown above.
Do you want to return a pair of (probably) numbers, or a single boolean?
Usually, tuple-s are different (mathematically) when any component is pairwise different. So I would code something like
bool operator != (PairXY a, PairXY b) { return a.x != b.x || a.y != b.y; }
but perhaps you want something else (but then, I won't call that !=).
Probably this is how your code should be.
class PairXY {
public:
PairXY( int _x, int _y): x(_x),y(_y){}
bool operator != (const PairXY a) {
return(this->x != a.x && this->y != a.y);
}
private:
int x;
int y;
};
int main ( int argc, char** argv ) {
return 0;
}