Operator overloading in C++ (operator-) - c++

I am working on a program to detect if one triangle is nested within another.
Here I created the struct point to define x and y as doubles.
struct Point {
double x;
double y;
};
Here is where I implement the struct:
double eval (LineSegment line, Point p)
{
Point p1 = p - line.StartPoint;
Point p2 = line.EndPoint - line.StartPoint;
return p2.x * p2.y - p1.y * p2.x;
}
When I compile it tells me, "no match for 'operator-' in 'p - line.LineSegment::StartPoint'."
I don't really understand what is happening, I guess it doesn't understand which 'point' I want since i use them together?
I did research and found operator overloading, but it was sort of confusing to me. I don't really know how to implement Operator Overloading.
If someone could show me how exactly to go about doing this, it would be helpful.

It means that the compiler has no idea how to subtract Point objects. It knows how to subtract built-in types, but to use operators with custom types, you need to provide the behavior.
In this case you probably want something like:
struct Point
{
double x;
double y;
Point& operator-=( const Point& that )
{
x -= that.x;
y -= that.y;
return this;
}
};
Point operator-(Point first, const Point& second)
{
return first -= second;
}
For more guidance, see our C++-FAQ entry on Operator Overloading. Lots of good advice in there that will help you avoid some of the pitfalls, as well as good examples and recommendations how to maximize code re-use and readability (which really means maintainability).
In this case, you should also ask yourself whether you want to differentiate between absolute and relative coordinate pairs. If you do, then the difference between two points should be a Size or Offset, and not a Point. (If you've ever used a library with DateTime and TimeSpan classes, you've seen this concept in action. C++ itself uses it for the Standard Library's time_point vs duration, both found in namespace std::chrono. You have a two dimensional version of that here.)

struct Point {
double x;
double y;
Point operator-(const Point& that) const
{
Point result;
result.x = this->x - that.x;
result.y = this->y - that.y;
return result;
}
};

If you want to subtract points, then you need to provide an overloaded operator to do it. C++ doesn't automatically generate arithmetic operations for class types, since most of the time they wouldn't make sense.
Something like this should do it:
Point operator-(Point lhs, Point rhs) {
return {lhs.x-rhs.x, lhs.y-rhs.y};
}
although I'd probably introduce a new type (Vector or Offset or something) for the return type, to prevent the category error of using the offset between points when you should use a point.

Here's a basic sketch to get you started:
Point operator-( const Point& lhs, const Point& rhs )
{
Point result;
// make sure this is what you want:
result.x = lhs.x - rhs.x;
result.y = lhs.y - rhs.y;
return result;
}
Note this is a free function, it doesn't go inside of Point's definition. Just put it afterwards.

Take a look at http://www.cplusplus.com/doc/tutorial/classes2/. It has a pretty good explanation on operator overloading.
What your code is saying is to subtract line.StartPoint from p. However, your struct doesn't have a defined behavior for that operation. So you can't use the syntax p - line.StartPoint unless you tell the compiler how to perform that operation with your struct.
The method signature in your struct will probably look something like this:
Point operator-(const Point &other) { }
You need to add the logic to that method that tells the compiler how to perform a subtraction operation on your struct.

If you add/subtract/multiply...etc two numbers together the compiler knows what you mean and everything's fine. If you want to subtract something that's a class, the compiler doesn't inherently know how to do that (for ANY class) but gives you a tool to define how to subtract two classes together and it looks like this (using your Point class):
Point operator-(Point p1, Point p2)
{
Point result;
result.x = p1.x - p2.x;
result.y = p1.y - p2.y;
return result;
}
Now the compiler knows how to subtract two points, by calling this function.

Related

Disambiguate template function specializations - value vs. reference

This question requires a bit of context - if you're feeling impatient, skip past the line break... I have a Vector-3,4 and Matrix-3,4 library defined in terms of template specializations; i.e., Vector<n> and Matrix<n> are defined in Matrix.hh, while non-trivial implementations (e.g., matrix multiplication, matrix inverse) have explicit specializations or instantiations in Matrix.cc for N = {3,4}.
This approach has worked well. In theory, an app could instantiate a Matrix<100>, but couldn't multiply or invert the matrix, as there are no implementation templates visible in the header. Only N = {3,4} are instantiated in Matrix.cc
Recently, I've been adding robust methods to complement any operation that involves an inner product - including matrix multiplications, matrix transforms of vectors, etc. Most 3D transforms (projections / orientations) are relatively well-conditioned, and any minor precision errors are not a problem since shared vertices / edges yield a consistent rasterization.
There are some operations that must be numerically robust. I can't do anything about how a GPU does dot products and matrix operations when rendering; but I cannot have control / camera parameters choke on valid geometry - and inner products are notorious for pathological cancellation errors, so the robust methods use compensated summation, products, dot products, etc.
This works fine for, say, Vector inner product in Matrix.hh :
////////////////////////////////////////////////////////////////////////////////
//
// inner product:
template <int n> float
inner (const GL0::Vector<n> & v0, const GL0::Vector<n> & v1)
{
float r = v0[0] * v1[0];
for (int i = 1; i < n; i++)
r += v0[i] * v1[i];
return r; // the running sum for the inner product.
}
float
robust_inner (const GL0::Vector<3> &, const GL0::Vector<3> &);
float
robust_inner (const GL0::Vector<4> &, const GL0::Vector<4> &);
////////////////////////////////////////////////////////////////////////////////
The implementations in Matrix.cc are not trivial.
I'm in more dubious territory when adding a robust method for [A]<-[A][B] matrix multiplication; perhaps the naming is not ideal:
template <int n> GL0::Matrix<n> &
operator *= (GL0::Matrix<n> & m0, const GL0::Matrix<n> & m1);
// (external instantiation)
GL0::Matrix<3> &
robust_multiply (GL0::Matrix<3> &, const GL0::Matrix<3> &);
GL0::Matrix<4> &
robust_multiply (GL0::Matrix<4> &, const GL0::Matrix<4> &);
There is a N = {3,4} implementation for the operator *= in Matrix.cc, but it relies on the naive inner product and is not robust - though typically good enough for GL / visualization. The robust_multiply functions are also implemented in Matrix.cc.
Now of course, I want the Matrix multiplication operator:
template <int n> GL0::Matrix<n>
operator * (GL0::Matrix<n> m0, const GL0::Matrix<n> & m1) {
return (m0 *= m1);
}
Leading me to the problematic definitions:
inline GL0::Matrix<3>
robust_multiply (GL0::Matrix<3> m0, const GL0::Matrix<3> & m1) {
return robust_multiply(m0, m1);
}
inline GL0::Matrix<4>
robust_multiply (GL0::Matrix<4> m0, const GL0::Matrix<4> & m1) {
return robust_multiply(m0, m1);
}
The call to robust_multiply(m0, m1) is ambiguous. Q: How can I force the LHS argument to be interpreted as a reference, ensuring a call to the previous function that modifies the (m0) argument. Obviously I can name robust_multiply as something else, but I'm more interested in utilizing the type system. I feel I'm missing something obvious in <utility> or <functional>. How do I force a call to the correct function?
(Sorry about the word count - I'm trying to clarify my own thinking as I write)
You named robust_multiply wrong.
*= and * are fundamentally different operations. They are related, but not the same operation - different verbs.
Overloading should be used when you are doing the same operation on different nouns.
If you do that, then your problems almost certainly evaporate. Sensible overloads are easy to write.
In your case, you want to change between writing to an argument or not based on its l/r value category. That leads to ambiguity problems.
I mean, there are workarounds to your problem -- use std::ref or pointers, for example, or &, && and const& overloads -- but they are patches here.
Naming this in programming is hard. And here is a case were you should do that hard bit.
...
Now one thing you could do is bless the arguments.
template<class T>
struct robust{
T t;
explicit operator T&()&{return t;}
explicit operator T()&&{
return std::forward<T>(t);
}
// also get() methods
explicit robust(T&&tin):
t(std::forward<T>(tin))
{}
};
then override *= and * for robust wrapped matrices.
robust{a}*=b;
(have lhs must be robust to keep overload count down).
Now the verb is clear, I just dressed up the nouns.
But this is just an idea, and not use-tested.

Using Eigen::Geometry module with custom scalar type

II would like to use Eigen for linear algebra in a geometry project I am currently working on. It is a great library relatively small and easy to use and popular enough.
However, I would also like to use a custom defined "Double" class to be able to compare two floating point values in computer precision (something like the difference between the two must be smaller than a given precision). For my custom type, I have implemented most of the std::math c++11 functions and all operators (including unary -, conj, imag, abs2...). I did everything listed in these links :
http://eigen.tuxfamily.org/dox-devel/TopicCustomizingEigen.html
https://forum.kde.org/viewtopic.php?f=74&t=26631
However, I still get compilation errors in Eigen Jacobi.h file, more specifically at line 340,341 which are :
x[i] = c * xi + numext::conj(s) * yi;
y[i] = -s * xi + numext::conj(c) * yi;
I get the following error from the compiler (Vs 2012, Win32, Release and Debug Configuration)
eigen\src/Jacobi/Jacobi.h(341): error C3767: '*': candidate function(s) not accessible
operator* is define in my custom type for the following cases :
CustomType operator*(CustomType const &_other);
CustomType operator*(double const &_other);
double operator*(CustomType const &_other);
I tried to define conj in the following manners :
CustomType conj(CustomType const &_type){return _type;}
double conj(customType const &_type){return _type.get();}
I tried defining conj in Eigen::numext namespace as well as in my CustomType namespace with no success.
Anyone has a hint, link, suggestion or know something Eigen needs I might have forgotten ?
Most likely because your code isn't const correct.
Your operator overloads should be:
CustomType operator*(CustomType const &_other) **const**;
CustomType operator*(double const &_other) **const**;
double operator*(CustomType const &_other) **const**;
If eigen has a const reference to an object of type CustomType it cannot call your operators because they are not const declared.
I.e.
void foo(const CustomType& x, const CustomType& y){
x * y; // Compile error, cannot call non-const operator * on const object.
}
Not sure if this is the problem here, but you have to specialize Eigen::NumTraits<T>. See this manpage.
Also I don't understand how you can have two conj functions with the same arguments which return different types.

Efficient functional style (C++11 ok)

Lets say I have the following:
struct point
{
double x;
double y;
double z;
};
I can write the following:
void point_mult(point& p, double c) { p.x *= c; p.y *= c; p.z *= c; }
void point_add(point& p, const point& p2) { p.x += p2.x; p.y += p2.y; p.z += p2.z; }
So I can then do the following:
point p{1,2,3};
point_mult(p, 2);
point_add(p, point{4,5,6});
This requires no copies of point, and only two constructions, namely the construction of point{1,2,3} and the construction of point{4,5,6}. I believe this applies even if point_add, point_mult and point{...} are in separate compilation units (i.e. can't be inlined).
However, I'd like to write code in a more functional style like this:
point p = point_add(point_mult(point{1,2,3}, 2), point{4,5,6});
How can I write point_mult and point_add such that no copies are required (even if point_mult and point_add are in separate compilation units), or is functional style forced to be not as efficient in C++?
Let's ignore the implicit fallacy of the question (namely that copying automatically means reduced efficiency). And let's also ignore the question of whether any copying would actually happen, or whether it would all be elided away by any half-decent compiler. Let's just take it on face value: can this be done without copying?
Yes, and it is probably the only other legitimate use for r-value references (though the previously ignored stipulations make this use case dubious):
point &&point_mult(point &&p, double c);
Of course, this will only bind to temporaries. So you would need an alternate version for l-values:
point &point_mult(point &p, double c);
The point is that you pass the references through as they are, either as references to temporaries or references to l-values.
It can be done with really ugly template metaprogramming. For example eigen uses templates so that expressions like matrix1 + matrix2 * matrix3 don't need to create any temporaries. The gist of how it works is the + and * operators for matrices don't return Matrix objects but instead return some kind of matrix expression object which is templatized on the types of the expression paramaters. This matrix expression object can then compute parts of the expression only when they are needed instead of creating temporary objects to store the result of subexpressions.
Actually implementing this can get quite messy. Have a look at Eigen's source if your interested. Boost's uBlas also does something similar, though it's not as extensively as eigen.
An efficient (and generalized) technique is expression templates. You can read a nice introductory explanation here.
It's difficult to implement and being based on templates, you cannot use separate compilation units, but it's very efficient. An interesting application in symbolic computation is parsing: Boost.Spirit builds very efficient parsers out of them.
C++11 auto keywords helps usage on practical programming tasks, as always when dealing with complex types, see this other answer.
First, why not use "better" functions ?
struct Point {
double x;
double y;
double z;
Point& operator+=(Point const& right) {
x += right.x; y += right.y; z += right.z;
return *this;
}
Point& operator*=(double f) {
x *= f; y *= f; z *= f;
return *this;
}
};
Now it can be used as:
Point p = ((Point{1,2,3} *= 2) += Point{4,5,6});
But I truly think that you worry too much about copies here (and performance).
Make it work
Make it fast
If you don't have anything that already works, talking about performance is akin to chasing mills... bottlenecks are rarely where we thought they would be.
Change the definition of point_mult() to:
point& point_mult(point& p, double c) { p.x *= c; p.y *= c; p.z *= c; return p; }
^^^^^^ ^^^^^^^^^
And call it as:
point & p = point_add(point_mult(*new point{1,2,3}, 2), point{4,5,6});
^^^ ^^^^^
there is no copy involved. However, you have to later do delete &p; for releasing the memory.

How to use an iterator?

I'm trying to calculate the distance between two points. The two points I stored in a vector in C++: (0,0) and (1,1).
I'm supposed to get results as
0
1.4
1.4
0
But the actual result that I got is
0
1
-1
0
I think there's something wrong with the way I use iterator in vector.
How can I fix this problem?
I posted the code below.
typedef struct point {
float x;
float y;
} point;
float distance(point *p1, point *p2)
{
return sqrt((p1->x - p2->x)*(p1->x - p2->x) +
(p1->y - p2->y)*(p1->y - p2->y));
}
int main()
{
vector <point> po;
point p1; p1.x = 0; p1.y = 0;
point p2; p2.x = 1; p2.y = 1;
po.push_back(p1);
po.push_back(p2);
vector <point>::iterator ii;
vector <point>::iterator jj;
for (ii = po.begin(); ii != po.end(); ii++)
{
for (jj = po.begin(); jj != po.end(); jj++)
{
cout << distance(ii,jj) << " ";
}
}
return 0;
}
That your code compiles at all is probably because you have a using namespace std somewhere. (Otherwise vector would have to be std::vector.) That's something I would advise against and you have just provided a good case why:
By accident, your call picks up std::distance(), which takes two iterators and calculates the distance between them. Remove the using directive and prefix all standard library types with std:: and the compiler will tell you that you tried to pass a vector <point>::iterator where a point* was required.
To get a pointer to an object an iterator points to, you'd have to dereference the iterator - which gives a reference to the object - and take the address of the result: &*ii.
(Note that a pointer would perfectly fulfill all requirements for a std::vector iterator and some earlier implementations of the standard library indeed used pointers for that, which allowed you to treat std::vector iterators as pointers. But modern implementations use a special iterator class for that. I suppose the reason is that using a class allows overloading functions for pointers and iterators. Also, using pointers as std::vector iterators encourages mixing pointers and iterators, which will prevent the code to compile when you change your container.)
But rather than doing this, I suggest you change your function so that it takes references instead (see this answer for why that's a good idea anyway.) :
float distance(const point& p1, const point& p2)
{
return sqrt((p1.x - p2.x)*(p1.x - p2.x) +
(p1.y - p2.y)*(p1.y - p2.y));
}
Note that the points are taken by const references. This indicates to the caller that the function won't change the points it is passed.
Then you can call it like this: distance(*ii,*jj).
On a side note, this
typedef struct point {
float x;
float y;
} point;
is a C-ism unnecessary in C++. Just spell it
struct point {
float x;
float y;
};
That would make problems if this struct definition ever was to parse from a C compiler (the code would have to refer to struct point then, not simply point), but I guess std::vector and the like would be far more of a challenge to a C compiler anyway.
By coincidence, you're actually using a built-in STL function "distance", which calculates the distance between iterators, instead of calling your own distance function. You need to "dereference" your iterators to get the contained object.
cout << distance(&(*ii), &(*jj)) << " ";
As you can see from the syntax above, an "iterator" is quite a lot like a generalized "pointer". The iterator cannot be used as "your" object type directly. In fact iterators are so similar to pointers that many standard algorithms that operate on iterators work fine on pointers as well.
As Sbi noted: your distance function takes pointers. It would be better rewritten as taking const references instead, which would make the function more "canonical" c++, and make the iterator dereference syntax less painful.
float distance(const point& i_p1, const point& i_p2)
{
return sqrt((p1.x - p2.x)*(p1.x - p2.x) +
(p1.y - p2.y)*(p1.y - p2.y));
}
cout << distance(*ii, *jj) << " ";
You might do a couple of things:
Make the distance() function take references to point objects. This is really just to make things more readable when calling the distance() function:
float distance(const point& p1, const point& p2)
{
return sqrt((p1.x - p2.x)*(p1.x - p2.x) +
(p1.y - p2.y)*(p1.y - p2.y));
}
Dereference your iterators when calling distance()so you're passing the point objects:
distance( *ii, *jj)
If you don't change the interface of the distance() function, you might
have to call it using something like the following to get appropriate
pointers:
distance( &*ii, &*jj)

C++ operator + and * non-const overloading

I have the following tricky problem: I have implemented a (rather complicated) class which represents mathematical functions in a multiwavelet basis. Since operations like +, - and * are quite natural in this context, I have implemented overloaded operators for this class:
FunctionTree<D> operator+(FunctionTree<D> &inpTree);
FunctionTree<D> operator-(FunctionTree<D> &inpTree);
FunctionTree<D> operator*(FunctionTree<D> &inpTree);
There operators work finer in simple, non-chained operations, and even in some cases when chaining the operators. Statements like
FunctionTree<3> y = a * b + c;
FunctionTree<3> z = a * b + b;
compile and seemingly work fine. The first line is actually ok, but the second line causes valgrind to tell you grim stories about memory being freed inside already freed regions and uninitialized variables being accessed. Furthermore, a statement like
FunctionTree<D> y = a + b * c;
will not even compile, because I have not defined (an ambiguous operator taking an actual object, not a reference, as argument). Of course the solution is clear: All arguments, and methods ought to be made const, and perhaps even return a const object or reference. Unfortunately this is not possible, since NONE of the objects involved are constant during the operations! This may sound strange, but this is an unavoidable consequence of the mathematics involved. I can fake it, using const_cast, but the code is still wrong!
Is there a way to solve this problem? The only solution I have currently is to make the return objects const, thus effectively disabling the operator chaining.
Regards, .jonas.
If your objects are 1GB (I guess that's memory they allocate on the heap, not their actual sizeof size), you probably shouldn't be supporting these operators on them. The problem is that your examples of operator chaining more or less presume immutable objects as its basic model of "what's going on", and create lots of temporaries to serve as intermediate results. You can't count on the compiler to be able to re-use the space efficiently. But you also can't copy 1GB objects willy-nilly.
Instead, you should only support the various assigning operators. Then your client instead of writing:
y = a * b + c;
which is liable to create enormous temporaries, should instead write:
// y = a * b + c
y = a;
y *= b;
y += c;
That way the user can keep a lid on things. It's easily seen that no temporaries are created, and you won't accidentally write a simple line of code that requires 18GB to run. If you want to do:
y = a * b + c * d;
then your code must explicitly note that a temporary result is required here (assuming you can't trash any of a, b, c, d):
// y = a * b + c * d
y = a;
y *= b;
{
FunctionTree x = c;
x *= d;
y += x;
}
but if the caller happens to know that for example c isn't needed after this, you can explicitly do:
// y = a * b + c * d [c is trashed]
c *= d;
y = a;
y *= b;
y += c;
In theory the compiler might be up to working all this stuff out for itself based on big expression with the chained operators, and data-flow analysis to show that c is unused. Good compilers with lots of optimisation switched on are good at this for integer arithmetic, so the machinery is there. In practice I wouldn't count on it. If the compiler cannot prove that the constructor and destructor of FunctionTree have no observable side-effects, then its ability to skip them is limited to the specific cases of legal "copy elision" in the standard.
Or you could look at the C interface to GMP to see how this is done without operator overloading at all. All the functions there take an "out parameter", which the result is written to. So for example if x is a huge multiple precision integer, that you want to multiply by 10, you choose whether to write:
mpz_mul_ui(x, x, 10); // modifies x in place, uses less memory
or:
mpz_t y;
mpz_init(y);
mpz_mul_ui(y, x, 10); // leaves x alone, result occupies as much memory again.
There is no simple solution to this problem. Your binary operators are (correctly) producing nameless temporary objects - such objects cannot be bound to non-const reference parameters.
One possible way round this is to forgo the chaining of operators - for a class X:
X a;
X b;
X c = a * b;
X d;
X e = c + d;
Another (rather horrible) solution is to make the the data members of the class mutable - that way they would be logically const but physically alterable. You would then make your parameters be const references. Like I said, this is horrible and may cause other problems.
You can use proxies instead of real values, and proxies can be constant, as they are not going to be changed. Below is a small example of how it might look like. Be aware that all the temporaries are still going to be created in that example but if you want to be smart, you can just save the operations, not the actual results of operations, and calculate only when someone wants to finally get result or a part of it. It might even speed up your code enormously as it helped APL
Also, you might want to make most of the members private.
#include <memory>
#include <iostream>
struct FunctionTreeProxy;
struct FunctionTree;
struct FunctionTreeProxy {
mutable std::auto_ptr<FunctionTree> ft;
explicit FunctionTreeProxy(FunctionTree * _ft): ft(_ft) {}
FunctionTreeProxy(FunctionTreeProxy const & rhs): ft(rhs.ft) {}
FunctionTreeProxy operator+(FunctionTree & rhs);
FunctionTreeProxy operator*(FunctionTree & rhs);
FunctionTreeProxy operator+(FunctionTreeProxy const & rhs);
FunctionTreeProxy operator*(FunctionTreeProxy const & rhs);
};
struct FunctionTree {
int i;
FunctionTree(int _i): i(_i) {}
FunctionTree(FunctionTreeProxy const & rhs): i(rhs.ft->i) {}
FunctionTree * add(FunctionTree & rhs) {
return new FunctionTree(i + rhs.i);
}
FunctionTree * mult(FunctionTree & rhs) {
return new FunctionTree(i * rhs.i);
}
FunctionTreeProxy operator+(FunctionTree & rhs) {
return FunctionTreeProxy(add(rhs));
}
FunctionTreeProxy operator*(FunctionTree & rhs) {
return FunctionTreeProxy(mult(rhs));
}
FunctionTreeProxy operator+(FunctionTreeProxy const & rhs) {
return FunctionTreeProxy(add(*rhs.ft));
}
FunctionTreeProxy operator*(FunctionTreeProxy const & rhs) {
return FunctionTreeProxy(mult(*rhs.ft));
}
};
FunctionTreeProxy FunctionTreeProxy::operator+(FunctionTree & rhs) {
return FunctionTreeProxy(ft.get()->add(rhs));
}
FunctionTreeProxy FunctionTreeProxy::operator*(FunctionTree & rhs) {
return FunctionTreeProxy(ft.get()->mult(rhs));
}
FunctionTreeProxy FunctionTreeProxy::operator+(FunctionTreeProxy const & rhs) {
return FunctionTreeProxy(ft.get()->add(*rhs.ft));
}
FunctionTreeProxy FunctionTreeProxy::operator*(FunctionTreeProxy const & rhs) {
return FunctionTreeProxy(ft.get()->mult(*rhs.ft));
}
int main(int argc, char* argv[])
{
FunctionTree a(1), b(2), c(3);
FunctionTree z = a + b * c;
std::cout << z.i << std::endl;
return 0;
}
"...NONE of the objects involved are constant during the operations! This may sound strange..."
No it doesn't sound strange, it sounds wrong.
If your operators modify the objects in a way that is observable from the outside, then that's an abuse of operator overloading.
If the objects are modified, because results are cached, make the cache mutable, so functions modifying the cache can still be declared const.
Pass the arguments by value rather than by reference?
EDIT: You may want to use += -= *= instead.