Call base class overloaded operator from parent class - c++

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;
// ~~~~~~~~~~~~~~~~^
}

Related

std::map with key as a struct with three int members [duplicate]

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);
}

comparing == operator for (struct &a, struct &b) vs (const struct &a, const struct &b)

I have defined a struct class called Point in my header file as follows -
namespace global_planner {
class GlobalPlanner : public nav_core::BaseGlobalPlanner {
struct Point {
__uint32_t x, y;
bool operator==(const Point &p1 ) {
return ((p1.x == x) && (p1.y == y));
}
bool operator<(const Point &p1 ) const {
return ((p1.x < x) || (p1.x == x && p1.y < y) ) ;
}
};
public:
///
private:
////
};
};
In my source file (named global_planner.cpp), I have a function named generate_straight_path defined as follows -
bool GlobalPlanner::generate_straight_path(const Point &p1, const Point &p2){
if(costmap_ros_->getCost(p1.x, p1.y) == costmap_2d::LETHAL_OBSTACLE) {
cout << "Point p1 is on obstacle!" << endl;
return false;
}
if(costmap_ros_->getCost(p2.x, p2.y) == costmap_2d::LETHAL_OBSTACLE) {
cout << "Point p2 is on obstacle!" << endl;
return false;
}
if(p1 == p2) {return 1;}
if(p1.x == p2.x){}
if(p1.y == p2.y){}
}
When I compile global_planner.cpp, I am getting the following error -
/home/skpro19/catkin_ws/src/my_global_planner/src/global_planner.cpp: In member function ‘bool global_planner::GlobalPlanner::generate_straight_path(const global_planner::GlobalPlanner::Point&, const global_planner::GlobalPlanner::Point&)’:
/home/skpro19/catkin_ws/src/my_global_planner/src/global_planner.cpp:150:11: error: no match for ‘operator==’ (operand types are ‘const global_planner::GlobalPlanner::Point’ and ‘const global_planner::GlobalPlanner::Point’)
if(p1 == p2) {return 1;}
The error disappears if I change the definition of generate_straight_path from generate_straight_path(const Point &p1, const Point &p2) to generate_straight_path(Point &p1, Point &p2).
Why is this happening?
Your equality operator overload is a member function, but not marked const:
bool operator==(const Point &p1 ) { return ((p1.x == x) && (p1.y == y)); }
When you turn it into a const member function, this should work as expected:
bool operator==(const Point &p1 ) const { return ((p1.x == x) && (p1.y == y)); }
It's a bit blurry through the operator, but when you look at it this way:
bool GlobalPlanner::generate_straight_path(const Point &p1, const Point &p2){
// ...
if (p1.operator==(p2)) /* ... */ ;
}
which is the more verbose way to call an member operator overload, you can see that this operator== must be const because the function argument const Point& p1 is const itself.
It is only by coincidence that you can fix it by removing a const. In fact you need to add one here:
bool operator==(const Point &p1 ) const { return ((p1.x == x) && (p1.y == y)); }
// ^^^
Otherwise you can only call operator== with a non-const left hand operand.

When using custom class in std::map with custom comparator -> error: static assertion failed

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. :)

C++ & Swap/Copy applied to a Point struct

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);
}

Can't use Operator != for bool

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;
}