It was very hard to come up with a title... (I'm not a native English speaker.)
struct A
{
int value;
A operator+(int i) const
{
A a;
a.value=value+i;
return a;
};
};
int main(){
A a;
a.value=2;
a=a+2;
return 0;
}
This code compiles/works as expected, but when I change a=a+2 to a=2+a, it won't compile anymore.
GCC gives me this error:
no match for ”operator+” in ”2 + a”
Is there any way to somehow make 2+a work just like a+2?
You need a free function, defined after the class
struct A
{
// ...
};
A operator+(int i, const A& a)
{
return a+i; // assuming commutativity
};
also, you might consider defining A& operator+=(int i); in A an implement both versions of operator+ as free functions. You might also be interested in Boost.Operators or other helpers to simplify A, see my profile for two options.
Sure, define the inverse operator outside the class:
struct A
{
int value;
A operator+(int i) const
{
A a;
a.value=value+i;
return a;
};
};
//marked inline to prevent a multiple definition
inline A operator+(int i, const A& a)
{
return a + i;
}
The other answers here work fine. However, another option you have is to create a constructor for a single int like this:
struct A
{
int value;
A(int i) {
value = i;
}
};
This allows integers to get implicitly converted, and allows you to only overload operators for your struct instead:
A operator+(const A& other) const
{
// All you need to do is work with an A, and associativity works fine
};
Of course, this does allow all integers to get implicitly converted to As, which may or may not be desirable.
Related
I just tried to make a function that compares 2 objects, but it gives me:
Error: bool Duree::operator==(const Duree&, const Duree&) must take exactly one argument
How can I solve this? Thank you.
Duree.h
#ifndef DEF_DUREE
#define DEF_DUREE
class Duree
{
public:
Duree(int heures = 0, int minutes = 0, int secondes = 0);
bool estEgal(Duree const& b) const;
bool operator==(Duree const& a, Duree const& b);
private:
int m_heures;
int m_minutes;
int m_secondes;
};
#endif
Duree.cpp
#include "Duree.h"
Duree::Duree(int heures, int minutes, int secondes) : m_heures(heures), m_minutes(minutes), m_secondes(secondes)
{
}
bool Duree::estEgal(Duree const& b) const
{
return (m_heures == b.m_heures && m_minutes == b.m_minutes && m_secondes == b.m_secondes);
}
bool operator==(Duree const& a, Duree const& b)
{
return a.estEgal(b);
}
Main.cpp
#include <iostream>
#include "Duree.h"
using namespace std;
int main()
{
Duree fisrt(10, 10, 10), second(15, 20);
if (fisrt == second)
cout << "Les durees sont identiques";
else
cout << "Les durees sont differentes";
return 0;
}
Either you declare operator== as a free function with two arguments:
bool operator==(Duree const& a, Duree const& b);
or as a member function with only one argument:
bool Duree::operator==(Duree const& b);
This is because when you do x == y you are comparing only two objects. If you have a member function there's an implicit "this object" (the one you call operator== on) passed, making it 3 arguments instead of 2.
That being said, from the way you wrote the code I'm guessing you just forgot to put friend in front of the operator== declaration, in the class definition.
Probably useful tip: You can use #pragma once, on compilers that support it (basically every "main" compiler), instead of include guards. :)
Change your prototype to bool operator==(Duree const& rhs); or make it a free function out of class Duree.
Always prefer the binary functions to be NON MEMBER (free) functions. Otherwise you can run into problems if you overload the operator with different types. Consider the following contrived code:
struct Foo {
int x;
bool operator==(Foo const & other) const { return x == other.x; }
};
This should work fine for comparing two Foos together. But it has a problem.
Suppose you also want to compare to an int:
struct Foo {
int x;
bool operator==(Foo const & other) const { return x == other.x; }
bool operator==(int other) const { return x == other; }
};
Now you can compare one way but not the other:
Foo a, b;
...
a == b; // ok
a == 123; // ok
123 == a; // ERROR
As member function the object must be on the right hand side.
Simple, move the int-Foo overloads out of the class, and make two versions, Foo==int and int==Foo? (Note, making them friends declared inside the class can accomplish that too, FWIW, but I'm not showing it here.)
struct Foo {
int x;
bool operator==(Foo const & other) const { return x == other.x; }
};
bool operator==(int other, Foo const& f) { return f.x == other; }
bool operator==(Foo const& f, int other) { return f.x == other; }
So now everything works, right? We have a mix of member and non-member operators.
a == b; // ok
a == 123; // ok
123 == a; // ok
Until Foo starts getting member functions that want to use the operators...
struct Foo {
int x;
bool operator==(Foo const & other) const { return x == other.x; }
void g(int x);
};
bool operator==(int other, Foo const& f) { return f.x == other; }
bool operator==(Foo const& f, int other) { return f.x == other; }
void Foo::g(int x)
{
Foo f = getOtherFoo();
if (f == x) { // ERROR! cannot find operator==(Foo,int)
//...
}
}
It STILL has a problem! Inside members of of Foo, it cannot see the non-member operators because the member one hides them! g() will not compile since it can't compare Foo to int. Moving all of the operators out will resolve it, since then all of the overloads are in the same scope.
(Remember, name-lookup keeps searching outer scopes UNTIL it finds the fist case of the name it is looking for, and then only considers all the names it finds in that scope. Inside g(), it's scope is in the class, and since it finds one version of the operator inside the class (the wrong one), it never looks outside the class for more overloads. But if they are all outside the class, it'll find them all at the same time.)
struct Foo {
int x;
void g(int x);
};
// NON MEMBER
bool operator==(Foo const & lhs, Foo const & rhs) { return lhsx == rhs.x; }
bool operator==(int other, Foo const& f) { return f.x == other; }
bool operator==(Foo const& f, int other) { return f.x == other; }
void Foo::g(int x)
{
Foo f = getOtherFoo();
if (f == x) { // OK now, finds proper overload
//...
}
}
Now, it compiles in all the cases. That's why they say, "Always prefer to make non-member binary operator overloads." Otherwise you can end up with symmetry and hiding problems.
I'm on the same kind of issue.
Worked by putting operator== with two arguments back in main.cpp before the main() ;)
I have this class :
class A
{
public:
//copy and move constructor,operator=
A func(const A& a,const A& b)
{
A c;
//do some stuff...
return c;
}
};
It works fine when I use it in this way :
A a;
A b;
A c=func(a,b);
But the problem is when I use it in this way :
A a;
A b;
a=func(a,b);
It does some unnecessary stuff (making c and in my class calling constructor is time consuming!)
I want to know if a is equal to one of variables that pass to function then I don't make c and do stuff in-place
After thinking for a while I came up with this solution :
class A
{
public:
//copy and move constructor and operator=
A func(const A& a,const A& b)
{
A c;
//do some stuff...
return c;
}
A func(const A& a,const A& b,bool inPlace)
{
if(!inPlace)
return func(a,b);
else
{
//const-cast a then do stuff on a
return a;
}
}
};
now It works fine with :
A a;
A b;
A c=func(a,b);
a=func(a,b,true);
But still it doesn't work with :
A a;
A b;
b=func(a,b,true);
So another overload for func is needed .
But It seems a bad design . Any better idea for making this class ?
Note that I don't want to make func like this :
void func(const A& a,const A& b,A& result)
(And sorry about the question title I cant find a better one :) )
EDIT
My constructor looks like this :
A(unsigned int SIZE)
{
// all of these are vectors and SIZE is about 1k
realData_.reserve(SIZE);
timePerUnit_.reserve(SIZE);
prob_.reserve(SIZE);
//....
// some math stuff for filling them
}
From how I understand your question you want to write a A &func(const A& a,const A& b) which returns a newly constructed A. But as an optimization you want to modify a or b and not construct a new A if the result of func is assigned to a or b.
When you are writing a = func(a, b) this is like a.operator=(func(a, b)). func will not know how its return value is used and operator= will not know that its parameter is coming from func. If you want to optimize for that special case you need to write extra functions for it.
You could write an unoptimized and an optimized version:
A &func(const A& a, const A& b) { A c; ...; return c; }
void func(A& a, const A& b) { modify a; }
void func(const A& a, A& b) { modify b;}
// In case func(a,b)==func(b,a) for const a and const b you can write:
void func(const A& a, A& b) { func(b, a); }
Or you could write a generic version:
void func(const A& a, const A& b, A& result)
{
if(&result == &a)
optimized modify result;
else if(&result == &b)
optimized modify result;
else
unoptimized modify result;
}
In case you are lucky you do not even need to distinguish between the different cases in the generic version. But this depends on the calculations you are doing.
BTW, if you are looking at the STL you will see that they are doing something similar. Replace A with string and func with operator+ and you will end up with string operator+ (const string& lhs, const string& rhs);. This operator will always create a new object which it returns. To optimize for the case str1 = str1 + str2; the STL declares an extra function operator+=. That's the same thing that you will need to do - only that your functions have the name func and not operator ... .
If you definitely don't want to use:
void func(const A& a, const A& b, A& result)
Then you can get away with a single overload by using a pointer for your third argument instead of a bool, like:
A func(const A& a, const A& b, const A* resultPlace = NULL)
{
if (resultPlace == &a) {
// Do in place stuff with a
return a;
}
else if (resultPlace == &b) {
// Do in place stuff with b
return b;
}
else {
A c;
// whatever
return c;
}
}
Of course, you would call this like: b = func(a, b, &b);
Not sure if you can do any better than this, but I doubt you'll be able to do what your question title asks specifically.
I am learning templates and operator overloading. I have written some code but I am confused... Let me explain...
template <class T>
class tempType
{
public:
T value;
bool locked;
tempType():locked(false)
{
value = 0;
}
T operator=(T val)
{
value=val;
return value;
}
tempType<T> operator=(tempType<T> &val)
{
value=val.value;
return *this;
}
operator T()
{
return value;
}
};
And I did...
int main(void)
{
tempType<int> i;
tempType<bool> b;
tempType<float> f;
i.value = 10;
i = i + f;
return 0;
}
What code I need to write in order to execute
tempType<T> operator=(tempType<T> &val){}
Also, I why operator T() is required?
Unless you implement move semantics, operator= should always take a const & reference to the source value. It should also return a reference to the modified object.
tempType & operator=(T const & val)
{
value=val;
return * this;
}
operator T is an implicit conversion function which allows any tempType object to be treated as an object of its underlying type T. Be careful when specifying implicit conversions that they won't conflict with each other.
An implicit conversion function usually shouldn't make a copy, so you probably want
operator T & ()
{
return value;
}
operator T const & () const
{
return value;
}
Given these, you shouldn't need another overload of operator = because the first overload will simply be adapted by the conversion function to a call such as i = b;.
If a series of conversions will result in the operator=(T const & val) being called, you should avoid also defining operator=(tempType const & val) because the overloads will compete on the basis of which conversion sequence is "better," which can result in a brittle (finicky) interface that may refuse to do seemingly reasonable things.
I think I know all the answers so I might as well post full response.
To override default operator= you should declare it as tempType<T> operator=(const tempType<T> &val){}. Now you need to call the method explicitly via i.operator=(other_i).
If you correct the declaration you can use it like this:
tempType<int> i;
tempType<int> other_i;
i = other_i; // this is what you just defined
The operator T() is called a conversion operator. It is kind of reverse or counter part of the conversion constructor which in your case would be tempType(const &T value).
It is used to convert a class object into a given type. So in your case you would be able to write:
tempType<int> i;
int some_int;
some_int = i; // tempType<int> gets converted into int via `operator int()`
template <class T>
class tempType
{
public:
T value;
bool locked;
tempType() : value(), locked(false)
{
value = 0;
}
//althought legal, returning something different from tempType&
//from an operator= is bad practice
T operator=(T val)
{
value=val;
return value;
}
tempType& operator=(const tempType &val)
{
value=val.value;
return *this;
}
operator T()
{
return value;
}
};
int main(void)
{
tempType<int> a;
tempType<int> b;
a = b;
return 0;
}
in the code, a = b calls the operator.
As for the second question, the operator T() is not needed "by default". In your example, it is used when you write i+f:
i is converted to an int
f is converted to a float
the operation (+) is performed
T tempType<int>::operator=(T val) is called for the assignement
How can I define operator ** such that it can perform exponentiation of 2 numbers . eg 2 ** 3. It should give answer as 8.
Or Indirectly is there any way I can do this with operator overloading instead of #define macros ?
You can't. You can only overload existing operators, and not for built in types.
You can't. You can only overload existing operators in C++; you cannot add new ones, or change the arity or associativity of existing operators. Even the preprocessor is powerless here - its identifiers cannot be symbols.
If you're willing to make a compromise w.r.t. ** and feel like obfuscating your code:
#include <cmath>
#include <iostream>
struct foo {
foo(int i) : i_(i) {}
int operator*(int exp)
{
return std::pow(i_,exp);
}
private:
int i_;
};
struct bar {
} power_of;
foo operator*(int i, bar)
{
return foo{i};
}
int main()
{
std::cout << 2 *power_of* 3; // prints 8
}
Otherwise, just use std::pow.
Like the other answers noted, this isn't possible for built-in types BUT you can get this to work for custom types like so (minimum code sample):
#include <cmath>
#include <iostream>
struct dummy;
struct Int
{
int i;
Int() : i(0) {}
Int(const int& i) : i(i) {}
dummy operator*();
};
struct dummy
{
Int* p;
dummy(Int* const p) : p(p) {}
int& operator*()
{
return p->i;
}
};
dummy Int::operator*()
{
return dummy(this);
}
int operator*(const Int& lhs, const dummy& rhs)
{
return std::pow(lhs.i, rhs.p->i);
}
int main()
{
Int a(2);
Int b(2);
std::cout<< a ** b << std::endl;
}
Live example
As others have noted: that isn't possible. You can overload another operator, like ^, for exponentiation, instead however on a simple type wrapper class/object.
But, if you're adventurous, another way, is to create a micro DSL that supports on-the-fly calculation of such an operator. (A famous example of that is LISP in C++)
However, given the effort involved, it may or may not be your cup of tea. However, it's worth knowing that such a possibility exists.
UPDATE:
Operator-Overloading works by overloading already existing operators. Why? Because if you could define your own, you will also have to define the precedence of such operators which can easily give way to abusing operators by abstracting away their original purpose - which increases difficulty when reading code. (At least that's the argument that's been made).
The closest operator that has a semantic meaning close to ** is the caret operator. A naive and illustrative implementation of such an operator is:
#include <iostream>
#include <cmath>
class Int {
public:
Int() {}
Int(int i) : value(i) {}
friend double operator^(const int& i, const Int& integer);
friend double operator^(const Int& integer, const int& i);
friend double operator^(const Int& lhs, const Int& rhs);
private:
int value;
};
double operator^ (const int& lhs, const Int& rhs) {
return std::pow(lhs, rhs.value);
}
double operator^ (const Int& lhs, const int& rhs) {
return std::pow(lhs.value, rhs);
}
double operator^ (const Int& lhs, const Int& rhs) {
return std::pow(lhs.value, rhs.value);
}
int main() {
Int i1 = 10;
Int i2 = 3;
double result = i1 ^ i2;
std::cout << result;
return 0;
}
Unfortunately the set of operators that can be overloaded in C++ is fixed and does not include the ** operator. You might think of using operator^() instead, but it turns out that ^ has the wrong precedence to serve as an exponentiation operator.
In short, there's not much you can do about this, unfortunately.
You can't overload operators for built-in types. I'd use operator ^ for such purpose for custom types.
I am learning C++ and I was wondering if I could gain some insight into the preferred way of creating binary operators that work on instances of two different types. Here is an example that I've made to illustrate my concerns:
class A;
class B;
class A
{
private:
int x;
public:
A(int x);
int getX() const;
int operator + (const B& b);
};
class B
{
private:
int x;
public:
B(int x);
int getX() const;
int operator + (const A& A);
};
A::A(int x) : x(x) {}
int A::getX() const { return x; }
// Method 1
int A::operator + (const B& b) { return getX() + b.getX(); }
B::B(int x) : x(x) {}
int B::getX() const { return x; }
// Method 1
int B::operator + (const A& a) { return getX() + a.getX(); }
// Method 2
int operator + (const A& a, const B& b) { return a.getX() + b.getX(); }
int operator + (const B& b, const A& a) { return a.getX() + b.getX(); }
#include <iostream>
using namespace std;
int main()
{
A a(2);
B b(2);
cout << a + b << endl;
return 0;
};
If I would like to have symmetry among the two types, which method is the best approach in the above code. Are there any possible dangers in choosing one method over the other? Does this vary with the return type? Please explain! Thank you!
The best way is to define (outside of either class) int operator+ (const A& a, const B& b), and make it a friend function of both classes if needed. In addition, define
int operator+(const B& b, const A& a) {return a + b;}
To make it symmetric.
The big risk with this approach is that people tend to perceive + as a symmetric operator. The way this is written, it is not (unless your implementations re the same).
At a minimum, you should overload + as an external binary operator (not as a member), and then play with overloading it several times.
You have to be careful, though, to make sure that nothing becomes ambiguous.
Can you explain what you're trying to do? I can't think of many cases of different types where it makes sense to have the symmetric heterogenous operators.
The main argument for method 2 is that you get implicit type conversion on both operands, not just the second one. This might save confusion somewhere down the line.
Speaking of which, your example code defines implicit conversions from int to A and from int to B, via the 1-arg constructors on both classes. This could result in ambiguity later. But if you left out the "explicit" for brevity, fair enough.
I agree with Uri's warning, though: if you find yourself doing this, you may be writing an API that others will find confusing. How come an A plus a B is an int? Does it really make things easier for users that they are adding a and b, rather than calling getX themselves and adding the results?
Is it because users know perfectly well that A and B are wrappers for ints? If so, then another option is to expose conversions from A to int and B to int, via operator int(). Then a+b will return an int for a sensible reason, and you'll get all the other arithmetic operators too:
#include <iostream>
struct A {
int x;
explicit A(int _x) : x(_x) {}
operator int() {
return x;
}
};
struct B {
int x;
explicit B(int _x) : x(_x) {}
operator int() {
return x;
}
};
int main() {
A a(2);
B b(2);
std::cout << a + b << "\n";
std::cout << a - b << "\n";
}
I read in a comment that your intended use is adding vectors and matrices. Maybe you should consider using only matrices where vectors are one dimensional matrices. Then you are left with just one type and one set of operators:
matrix operator*( matrix const& a, matrix const& b );
matrix operator+( matrix const& a, matrix const& b ); // and so on
If you want to keep the vector class then you should consider whether you also want a transposed vector (maybe transpose is just an internal property of vector).
The set of operations is not really symmetric:
vector * matrix = vector
matrix * vector_t = vector_t
matrix * matrix = matrix
vector_t * vector = matrix
vector * vector_t = int
and you should offer those three operations (assuming transpose is a property of vector):
vector operator*( vector const& v, matrix const& m );
vector operator*( matrix const& m, vector const& v );
matrix operator*( matrix const& m1, matrix const& m2 );
matrix operator*( vector const& v1, vector const& v2 ); // possibly 1x1 matrix, you cannot overload changing only return value
All as free functions if possible. Even if the above set is not symmetric, neither is the real world and your users will expect it.