Overload an operator twice [duplicate] - c++

This question already has answers here:
Overloading by return type
(11 answers)
Closed 8 years ago.
It's possible to overload the same operator twice on C++?
When I try to overload the + operator using the return type as a base, the compiler show me an error.
bigint.h:41:9: error: ‘std::string BigInt::operator+(BigInt)’ cannot be overloaded
bigint.h:40:9: error: with ‘BigInt BigInt::operator+(BigInt)’
This is my code:
.h:
BigInt operator + (BigInt);
string operator + (BigInt);
.cc:
BigInt BigInt::operator + (BigInt M){
if (this->number.size() != M.number.size())
fixLength (this->number, M.number);
// Call Sum;
this->number = Sum (this->number, M.number);
return (*this);
}
string BigInt::operator + (Bigint M){
// Call BigInt overload +;
}
Edit: Apparently I cannot overload the same operator twice using the return type as a base. Suggestions?

As has been pointed out, you cannot overload beased on return type alone. So this is fine:
Foo operator+(const Foo&, const Foo&);
Foo operator+(const char*, double);
but this is not:
Foo operator+(const Foo&, const Foo&);
Bar operator+(const Foo&, const Foo&);
But most of the time there are valid and simple solutions to a given problem. For instance, in a situation like yours, where you want the following to work:
Foo a, b;
Foo c = a + b;
Bar bar = a + b;
then a common strategy is to either give Bar an implicit converting constructor:
struct Bar
{
Bar(const Foo& foo) { .... }
};
or give Foo a conversion operator:
struct Foo
{
explicit operator Bar() { .... }
....
};
Note you can't mark the operator explicit if you don't have a C++11 compiler.

method overload in C++ is by argument list, not the return value.. so in your case, the two methods are ambiguous and the compiler can't tell which one to use (they have the same argument list)

No, you can't overload based on the return type.
From standard docs., Sec 13.1.2,
Function declarations that differ only in the return type cannot be overloaded.
What this means is that methods can be overloading only if they differ by parameters. As with C++, a method's return type is not considered part of the method signature.
Check Wiki for Name Mangling for more details

Related

Operator overloading for primitive types in C++

In C++, if you've got a class Foo, and you want users of Foo to be able to write:
Foo x;
x += 3;
, you can simply make a member function of Foo, Foo& operator+=(int rhs). If you want to be able to write:
Foo x;
int y = 3;
y += x;
, you cannot accomplish this by writing a member function of Foo, instead one has to write an external function, which usually must be declared as a friend of Foo.
How hard would it be for a future version of C++ to say that this can be written with a Foo member function int& operator+=(int &lhs, Reversed), where Reversed was some empty class whose sole purpose was to distinguish the two versions of the operator?
If this were done, it could probably eliminate the vast majority of the uses of the friend keyword in new code.
You can in fact define such an operator, because you are free to overload += for built-in types:
int& operator+=(int &lhs, Foo &rhs) {
lhs += rhs.somefield;
return lhs;
}
On the other hand, instead of writing overloaded functions for all possible operators, you can also provide a function that will allow implicit casts of class Foo to int:
class Foo {
... somefield;
operator int() {
return (int)somefield;
}
};

Non-friend single-line operator + overload based on operator +=

Let's say I have a class:
class A
{
//...
};
With well defined operator +=:
A& operator +=(const A&) {return *this;} //class without members
So let's try to overload operator+ also (as non-friend). I don't want to use class name to call constructor of temporary object (kinda want this make generic code):
A operator +(const A& other) const
{
return auto(*this)(*this) += other; //error: invalid use of auto
// /\/\/\/\/\ /\
// type of *this ||
// constructor call
}
auto is no good here. Let's try decltype.
A operator +(const A& other) const
{
return decltype(*this)(*this) += other; //error: 'A& A::operator+=(const A&)' discards
// /\/\/\/\/\/\/\ /\ qualifiers [-fpermissive] return
// type of *this || decltype(*this)(*this) += other;
// constructor call ^
}
This managed to get the type out of *this, but operator+ is declared const, so we got const A deduced (that's what I thought). So let's go on:
A operator +(const A& other) const
{
return typename std::remove_const<decltype(*this)>::type(*this) += amount;
//same error as previous
}
Now I got mindblown. Even thought I removed constness, it still discards
qualifier. Well, maybe that's because all I was doing was just CASTING. So stupid. To call a constructor I would have to generate code that (besides type) has ::Constructor (so I even tried to make an alias for constructor, but at this point I failed so hard). My broken brain gave up, but rest of my consciousness gave me an solution (which is generic in writing, so that's good):
// outside of class
template<class A>
inline A&& make_rvalue(A copy)
{
return std::move(copy);
}
// inside of class
A operator +(const A& other) const
{
return make_rvalue(*this) += other; // such generic code
}
That's what I ended with. But is there some trick that doesn't involve any other function call?
EDIT: I know classic methods of doing this, but what I search is described below:
operator is reduced to {return /*...*/;}
doesn't involve names of class methods or global functions
takes to account overloads with other types - it cannot take argument(s) by value, since class A != class B, argument int over const int& doesn't help much with Matrix class (but proxy operator that calls target operator with exchanged arguments is OK)
takes to account (possible) order of operation (x#y != y#x), where both should should have same return statement
return statement should be exacly the same for given operator# is every class that has overloaded operator +=
If you create a function like this:
template <typename T>
T add(T temp,const T &b)
{
temp += b;
return temp;
}
You can use it like this:
A operator+(const A& other) const { return add(*this,other); }
I'm going to go on record as saying this whole line of thinking/coding is going the wrong way. You already know that (in this case) the return type is A. Your code seems to be putting a lot of work into saying A in the most complex, indirect way possible.
A operator +(const A& other) const {
A ret {*this};
ret += other;
return ret;
}
Since you seem to really want to use C++11 features (even though in this case almost none of them provides any real help) I used a braced initializer, so it uses something from C++11. And no, this isn't one line, but it is readable.
Note that the same style is fine in generic code as well. For example, in a non-member overload of operator+, we might have something like this:
template <class T>
T operator+(T const &a, T const &b) {
T ret {a};
ret += b;
return ret;
}
This can be simplified a bit as well though:
template <class T>
T operator+(T ret, t const &b) {
ret += b;
return ret;
}
Again, we lose precisely nothing from the fact that older compilers can and will accept the code without problem.

How to return first operand if the second operand of + operator overloading is zero in C++?

I have this class definition:
class foo{
public:
foo();
foo(const int& var);
foo(const foo& var);
~foo();
const foo operator +(const foo& secondOp) const;
private:
int a;
//plus other values, pointers, e.t.c.
};
Also I have made this implementation for '+' operator overloading:
const foo foo::operator +(const foo& secondOp) const{
//I want here to check if i have one operand or two...
if ((FIRST_OPERAND.a!=0) && (secondOp.a==0)){
cout << "ERROR, second operand is zero";
return FIRST_OPERAND;
}
else if ((FIRST_OPERAND.a==0) && (secondOp.a!=0)){
cout << "ERROR, first operand is zero";
return secondOp;
}
}
When i write in main():
foo a(2);
foo b;
foo c;
//I want here to print the ERROR and
//return only the values of a
c = a + b;
Ηow can i return the value of the first operand if the second operand is zero and vice versa?
You're almost there. Since it's a member function, the first operand is *this, so replace FIRST_OPERAND.a with this->a or just a.
However, it might be better to make it a non-member function to allow conversions on both operands (i.e. to be able to write a + 2 or 2 + a). It will need to be a friend in order to access the private member(s).
friend foo operator +(const foo& firstOp, const foo& secondOp);
Also, it's best not to return a const value as that prevents moving from the return value.
It is the compiler that checks the syntaxical correctness of the program. It is unable to distinguish whether you indeed wanted to write
c = a;
that is to do the assignment or you wanted to write
c = a + b;
The both statements are correct.
It is a so-called logical error. The compiler is unable to see what we thoght.
For your line c = a; The assignment operator is implemented by the compiler (just shallow copying the object memory).
That is the reason your code compiles "without the second operand".
If you wish to disallow using the assignment operator - hide it. E.g. by implementing with the private access modifier.
You have to define this function as a friend function
friend Int operator + (int first, Int &second);
this function can perform obj + 2 or 2 + obj.
Int operator + (int first, Int& second){
second.a += first;
return second;
}

Is it possible to use a friend function to convert a class-type a basic-type? [duplicate]

This question already has answers here:
Non-member conversion functions; Casting different types, e.g. DirectX vector to OpenGL vector
(3 answers)
Closed 8 years ago.
Is it possible using friends?
class MyClass
{
private:
int myInteger;
float myFloat;
public:
void SetData(int a, float b)
{
myInteger = a;
myFloat = b;
}
operator int();
friend operator float(MyClass & );
};
MyClass :: operator int()
{
return myInteger;
}
operator float(MyClass & obj)
{
return obj.myFloat;
}
This code doesn't compile. How to do it in a correct way?
VS2008 says:
error C2801: 'operator float' must be a non-static member
Why not making op float a member?
operator float(){ return myFloat;}
If overloading the operator isn't working for you, consider using a named function:
float ToFloat(MyClass & obj)
{
return obj.myFloat;
}
This will also avoid implicit conversions... but I suppose if you were planning on overloading the operator your intention was to allow the implicit conversion.

Overloading Arithmetic Operators

The assignment operator can be declared as
T& operator= (const t&);
in a class, but the arithmetic operators cannot be defined that way. It has to be friend function. I don't understand why? Can you please explain ?
It is not mandatory that arithmetic operators should be friend
Well you can define like this:
MyClass MyClass::operator + (const MyClass& t) const
{
MyClass ret(*this);
ret += t;
return ret;
}
The a + b is really a syntax sugar, the compiler will expand it to a.operator+(b). The previous sample will work if all your objects are MyClass instances, but will not work if you have to operate with others types, ie 1 + a, will not work, this can be solved by using friends.
MyClass operator + (int i, const MyClass& t)
{
MyClass ret(i);
ret += t;
return ret;
}
This has to be done when the left hand side of the + operator is not a class, or it is a class but you can't add operator + to its definition.
I think that C++ FAQ Lite will give you a definitive answer.
They ideally should be globals and not necessarily friends, so that you can write:
yourtype v = 1;
yourtype w = 1 + v;
Since, 1 is not an object of yourtype, if the operator+ were a member it would throw a fit. However, making it global makes it convert the 1 to yourtype and then perform the operation. Making it a friend helps to extract and manipulate the members of yourtype as required -- though not required. As an example: You can implement the member function operator+= and use it in the implementation of the operator+.
The problem is that if you do something like this:
class A
{
A& operator+(int n);
// ...
}
int main()
{
A my_var;
int integer = 1;
A + integer; // compiles
integer + A // error: no function operator+(int, A) defined
}
it will not compile.
A solution is to define operator+(int, A) and operator+(A, int) as friends of A.
As a side note, the Boost Operators library makes this process very easy.