Sorry for asking a similar question that has been asked before, but I wasn't able to understand the answers.
Header file
float Dot(const Point& other) const;
CPP
Point Point::operator*(float operand) const
{
return Point(mX * operand, mY * operand);
}
and I am getting Error C2677: binary '*': no global operator found
what is the problem??
You have implemented operator* in the cpp file but in the header file you only declared a simple Dot function.
You either move the operator* inline in the header file or you add a declaration for it in the header file, ie:
Class Point {
[...]
Point operator*( float operand ) const {
return Point( mX * operand, mY * operand) );
}
};
That operator defined that way is a member operator because you have declared inside the class itself. You might also want to add a global operator, for example a comparison operator, which you will place outside your class declaration, for example:
Class Point {
[...]
Point operator*( float operand ) const {
return Point( mX * operand, mY * operand) );
}
};
bool operator==(const Point& left, const Point& right)
{
return left.value == right.value;
};
Final thought:
So to recap the error you've got it most probably means that you didnt' declare the operator* as global operator as shown above. Also I think you might confusing a dot product with a multiplication, (operator*), which held two very different results, also notice one is a scalar operation (in any dimension), the other is a Point, in this case, two dimension.
Related
I am working through a resource I found online for writing a library to handle arbitrary precision numbers.
I have created the two files BigInt.h, containing the definitions of all the functions, and BigInt.cpp, containing all the implementations of the functions.
Part of the program involves overloading an operator to return a call from a different function. For the sake of the question, I'll post the code as it comes from the example, even though I don't exactly understand why it works.
I define the operator overload here:
BigInt BigInt::operator / (const BigInt &v) const {
return divmod(*this, v).first;
}
This relies on the function implemented immediately above it, divmod. Implemented as follows:
friend pair<BigInt, BigInt> BigInt::divmod(const BigInt &a1, const BigInt &b1) {
... Do Things
return make_pair(q, r / norm);
}
I've left out the code before the return statement.
I am writing this using VC++15. When I hover over the error produced by return divmod(...).first;, Intellisense says:
Error: more than once instance of overloaded function "divmod" matches the argument list:
function "divmod(const BigInt &a1, const BigInt &b1)"
function "divmod(const BigInt &a1, const BigInt &b1)"
argument types are: (const BigInt &a1, const BigInt &b1)
*this is set via the constructor:
BigInt::BigInt(long long v) {
*this = v;
}
Any assistance you can provide would be helpful. I am able to provide more information if necessary.
For the sake of information, the original program was written in C and implemented in a struct rather than as a C++ class as I've done.
[Edit]
I was informed that I am using the function divmod as both a friend and member of class BigInt. To combat this, I took off the friend classifier and am simply leaving it as a public pair<> function. Below is the code relevant to this example
#includes and namespaces
class BigInt {
# Private Members
public:
BigInt(long long v){
*this = v
}
pair<BigInt, BigInt> BigInt::divmod(const BigInt &a1, const BigInt &b1) {
... Do things
return make_pair(q, r / norm);
}
BigInt BigInt::operator / (const BigInt &v) const {
return divmod(*this, v).first;
}
};
In doing this, Intellisense gives me a new error.
the object has type qualifiers that are not compatible with the member function "BigInt::divmod"
object type is: const BigInt
It is worth noting that I am not done "copying" over the code and I am missing several more functions (mostly operator overloads). That is why at this time I am using the Intellisense errors instead of the compiler errors (even though they are just a shorter version of the errors that Intellisense gives).
In the error it mentions that I am providing a qualifier being provided to the function is invalid (and doesn't tell me which parameter it is addressing). Could this mean that the *this = v line in the constructor isn't working because it's not a constant value?
Please let me know if I can give you any more information!
I am implementing a class Vector and defined the multiplication operator as a member of the class as
Vector operator*(const float& s);
as far as I understand, this means that the left operand is a Vector and the right operand is a float. So if I try and do something like this
Vector c(1,2,3);
Vector d = c * 2.0f; // Results in d = (2,4,6)
that's ok, however, to my eyes is weird to see first the vector then the scaling factor, so in order to have float * Vector I defined a non-member function as
Vector operator*(const float& s, const Vector& v)
{
//Invalid operands to binary expression 'const Vector' and 'float'
return v * s;
}
However I received the error in the comment. I don't know what am I missing or if this is not the way I should declare the operator in order to do the scaling in float * Vector fashion.
Notice that you're passing v as const Vector &, but your member operator* is not marked as const. So it can only be called on non-const Vector objects. This is most certainly not what you want, so just mark the member as const:
Vector operator*(const float& s) const;
I have seen comments or answers on SoF stating that overloading the cast operator to bool is dangerous and I should prefer the void* operator instead. Still I would like to ask if it is dangerous practice to use this operator in my use case and if yes why.
I implement a simply geometry library and one of its most basic classes is a point that I define in the following way:
struct point {
double x, y;
bool real;
point(double x_, double y_): x(x_), y(y_), real(true) {}
point(): x(0), y(0), real(true) {}
operator bool() {
return real;
}
};
I will try to explain why I need the cast operator to bool. I have another class called line and I have a function declared as follows:
point intersect(const line& a, const line& b);
Now having overloaded the cast operator to bool of a point I can write both: point p = intersect(a,b); and if (intersect(a,b)) thus either getting the intersection point of two lines or checking if two lines intersect. I use this in other places as well but I believe this example is enough to show the usage of the cast operator. Is my usage of the cast operator dangerous and if it is could you please give an example when the effect will not be as expected?
EDIT: one small addition thanks to juanchopanza : in this project I am limited to not using c++11, so I can not make the operator explicit.
That is not good enough. Since you're stuck with C++03, safe-bool idiom is what you should be using if you need such a thing at all (otherwise, explicit conversion function should be preferred).
An alternative solution is to return boost:optional instead:
boost::optional<point> intersect(const line& a, const line& b);
I would adopt this approach (even in C++11), as it looks semantically better — parallel lines don't have intersection point, so the return value should indeed be optional (or maybe value).
Yes, this is dangerous. Just for example, let's consider your point exactly as-is, with no definition of operator+. Despite that lack, if we try to add two point objects, the compiler won't object at all:
point a, b;
std::cout << a + b;
This works by converting each point to bool, then adding the bools. In an integer context, false converts to 0 and true converts to 1, so we can expect the code above to print out 2. Of course, I've just used addition as an example. You could just as well do subtraction, multiplication, division, bitwise operations, logical operations, etc. All of them will compile and execute, but obviously produce worthless results. Likewise, if we pass a point to some function that only accepts a numeric type, the compiler won't stop s or complain -- it'll just convert to bool, and the function will get either 0 or 1 depending on whether real was true or not.
The safe-bool idiom is safe (well, less dangerous anyway) because you can test a void * in a Boolean context, but a void * won't implicitly convert to much of anything else like bool will. You (mostly1) can't accidentally do arithmetic, bitwise operations, etc., on them.
1. There are a few holes anyway, mostly involving calling something else that does some sort of explicit conversion on the void *. Being able to mark conversion operators explicit is better, but honestly they give a lot more improvement in readability than safety.
Strange that those people didn't tell you why overloading operator bool() is dangerous.
The reason is that C++ has implicit conversion from bool to all other numeric types. So if you overload operator bool() then you lose a lot of type checks that users of the class would normally expect. They can supply a point anywhere that an int or float is expected.
Overloading operator void*() is less dangerous because there's less that void* converts to, but still has the same fundamental issue that the void* type is used for other things.
The idea of the safe bool idiom is to return a pointer type that doesn't convert to anything used in any API.
Note that there would be no need to worry about this if you were willing to write if (intersect(a,b).real), or perhaps if (intersect(a,b).exists()). C++03 does have explicit conversions. Any function with one parameter (or non-static member function with no parameters) is a conversion of sorts. C++03 just doesn't have explicit conversion operators.
You might run into all kind of trouble due to implicit conversions from bool to a numeric value.
Also, your line class got an (in my point of vew) dangerious member 'bool real', to carry results of function calls. An intersection function returning an intersection value or NaN if the lines do not intersect could resolve your problem.
Example
Having a (infinite) line class holding an origin p and a vector v:
struct Line {
Point p;
Vector v;
Point operator () (double r) const {
return p + r * v;
}
};
And a function calculating an intersection value
/// A factor suitable to be passed to line a as argument to calculate the
/// inersection point.
/// - A value in the range [0, 1] indicates a point between
/// a.p and a.p + a.v.
/// - The result is NaN if the lines do not intersect.
double intersection(const Line& a, const Line& b) {
double d = a.v.x * b.v.y - a.v.y * b.v.x;
if( ! d) return std::numeric_limits<double>::quiet_NaN();
else {
double n = (b.p.x - a.p.x) * b.v.y
- (b.p.y - a.p.y) * b.v.x;
return n/d;
}
}
Then you can do:
double d = intersection(a, b);
if(d == d) { // std::isnan is c++11
Point p = a(d);
}
Or
if(0 <= d && d <= 1) {
Point p = a(d);
}
For example, early in the C++ 2003 Standard class std::basic_ios had the following conversion operator
operator void*() const
Now as the new C++ Standard has keyword explicit this operator was substituted for
explicit operator bool() const;
So if you will add keyword explicit for your operator I think it will not be dangerous.:)
The other way is to define operator bool operator !() instead of the conversion operator.
Although there are already a few very good answers I would like to assemble a bit more complete answer with explanation of why the proposed solution does work.
1.Why is my solution wrong?
The compiler performs implicit conversions from bool to numeric types resulting in unexpected operators being defined. For instance:
point p;
if (p < 1)
Will compile while I did not expect it to. Changing the operator for conversion to operator void*() will improve the things but only slightly as there some operators(although less than for bool) that are defined for void * and their existence will result again in unexpected behavior.
2.So what is the correct solution. The correct solution can be found here. But I will include the code for my class so that I can explain why it works and why do we solve the problem in this way:
class point {
typedef void (point::*bool_type)() const;
void not_supported() const; // NOTE: only declaration NO body!
public:
double x, y;
bool real;
point(double x_, double y_): x(x_), y(y_), real(true) {}
point(): x(0), y(0), real(true) {}
operator bool_type() {
return (real == true)? &point::not_supported : 0;
}
template<typename T>
bool operator==(const T& rhs) const {
not_supported();
return false;
}
template<typename T>
bool operator!=(const T& rhs) const {
not_supported();
return false;
}
};
Now first I will explain why do we have to use a type that is a function pointer and not a plain pointer. The answer is stated by Steve Jessop in a comment below Nawaz's answer. function pointers are not < comparable, thus any attempt to write p < 5 or any other comparison between a point and some other type will fail to compile.
Why do we need to have an method with no body (not_supported)? Because in this way each time we try to instantiate the templated methods for comparison(that is == and !=), we will have a function call of a method with no body that will cause a compile error.
I am trying to overload the * operator in order to multiply two objects (dot product).
These objects can be Point3D, Vector3D or Normal. They all basically have the same structure (an x, y, and z value), I've only split them up for semantics.
The line that is giving me trouble is this:
float t = (point - r.origin)*normal / (r.direction * normal);
Here, point and r.origin are a Point3D, normal is a Normal and r.direction is a Vector3D. In the header files for these classes I have the following overload functions:
In Vector3D.h:
Vector3D operator *(Normal& n);
In Point3D.h:
Point3D operator -(Point3D& p);
Point3D operator *(Normal& n);
The error I get is:
No match for 'operator*' in 'r->Ray::direction * ((const Plane*)this)->Plane::normal'
Assuming I have correctly filled out the functions in the .cpp file, is there anything stupid I've done here? Also, ignore the fact that there is no division operator yet...It's in the pipeline!
Cheers
You may have defined the unary versions instead of the binary versions. (Did you define them inside the class { ... } ? )
Or you may have not defined them as const. Try this:
Vector3D operator *(const Normal& n) const;
Point3D operator -(const Point3D& p) const;
Point3D operator *(const Normal& n) const;
For binary functions over hetrogeneous parameters like this I find it a lot easier to define them all together at global scope in a seperate file/place and friend them from the classes.
Your this appears like it might be const (just guessing from the error message, since you haven't included that code in your question). Try:
Vector3D operator *(const Normal& n);
Point3D operator -(const Point3D& p);
Point3D operator *(const Normal& n);
I defined a class like this:
Quaternion& conjugate(); //negates the vector component of the quaternion
Quaternion conjugate() const; //same but in without modifying the class...
Quaternion& operator = (Quaternion const& Qrhs);
Quaternion& operator *= (Quaternion const& Q);
Quaternion operator * (Quaternion const& Qrhs) const;
now I use this functions like this:
PRINTVAR(*this); //this is the first time printed (a little macro to print line and file)
Quaternion vQ(0.,vn), resQ;
resQ = vQ*(this->conjugate()); //this is the method I want to discuss...
PRINTVAR(*this); //this is the second time
resQ = *this * resQ;
and this is the output
*this: (0:0:0:0) at line: 128 in file: Quaternions.cpp
*this: (-0:-0:-0:0) at line: 131 in file: Quaternions.cpp
I thought that by calling the operator * in the line resQ = vQ*(this should be called as const)...
why if I print *this again is changed?
here is the definition of the conjugate function:
Quaternion& Quaternion::conjugate(){
/* Given: Nothing
* Task: Invert sign of the vector
* Return: the class which will be modified
*/
V3 vec;
vec = -(this->getVector());
x() = vec[0];
y() = vec[1];
z() = vec[2];
return *this;
}
Quaternion Quaternion::conjugate() const{
Quaternion result(*this);
result.conjugate();
return result;
}
If the code you showed is in a non-const method, than the this pointer is non-const, and the non-const conjugate method is of course a better match than the const one. Return types aren't considered in overload decisions. If you want to insist that the const version is used, you can add constness: resQ = vQ*(static_cast<const Quaternion*>(this)->conjugate());
Probably the method in which you are using this is non-const.
The type of this a member function of a type A, is A * const. For const member function it is const A * const.
Therefore, your code will work as you expect it to do if you enter your code into const method.
If you want to force calling const overload of function you will need to do a const-cast:
const_cast<const Quaternion * const>(this)->conjugate();
*this is not const (although it is used in a const method), and the c++ FAQ Lite states regarding const overloading (in the FAQ's case on a subscript operator);
When you apply the subscript operator to a MyFredList object that is
non-const, the compiler will call the non-const subscript operator.
Translated, since *this is non-const, the non-const method will be called.