Whats wrong with my code shown below? please somebody throw some light. Thanks for your time !
#include<iostream.h>
using namespace std;
struct mydata{
int mx;
mydata(int x = 0){}
mydata operator+(const mydata& rhs){
mydata temp(rhs);
return temp;
}
operator int() const{ return mx; }
operator double() const{ return mx; }
};
int main(){
mydata d;
mydata r = d + 5; // L1
5 + d; // L2
d + d; // L3
}
First, you haven't stated what the problem is, but presumably you want an operator+ that sums the mx values of two mydata objects:
mydata operator+(const mydata& rhs){
return mydata (mx + rhs.mx);
}
Next, I would suggest making this a non-member function, so that the LHS and RHS get treated in the same way, fixing the problem in L2:
mydata operator+(const mydata& lhs, const mydata& rhs){
return mydata (lhs.mx + rhs.mx);
}
Finally, you will have an ambiguous overload remaining, because the compiler cannot decide whether to use the built-in operator+(int,int) or your own operator+(const mydata&, const mydata&). You can fix this by removing the cast operators int() and double().
See demo here.
The problem (stated the comment) is that compiler doesn't know which + you want to execute:
(double)d + 5
or
(int)d + 5
In order to resolve this ambiguoity, you should point the type conversion, or replace one of these operators by a named function:
operator int() const{ return mx; }
operator double() const{ return mx; }
If you want instead use d + mydata(5) you should write so, because the above variants are more likely to be applied
You could provide a few non-member operator+ to enable operator+ with different data type:
mydata operator+(const mydata& lhs, const mydata& rhs){
return mydata (lhs.mx + rhs.mx);
}
mydata operator+(int mx, const mydata& rhs){
return mydata (rhs.mx+mx);
}
mydata operator+(const mydata& lhs, int mx){
return mydata(lhs.mx+mx);
}
You can't do 5 + d. 5 can not be converted to class object like this. For this you need to get the operator + definition out of the class method. (in my knowledge preferably friend).
Related
Consider a class SomeClass:
class SomeClass{
public:
// Constructors, other members
float& operator[](const unsigned i);
friend bool operator==(const SomeClass &A, const SomeClass &B);
};
Suppose this is how the == operator is overloaded for this class (not the actual implementation, but an overly simplified version):
bool operator==(const SomeClass &A, const SomeClass &B){
if (A[0] == B[0])
return true;
return false;
}
This would throw a compiler error, since the overloaded [] operator requires the instance to be non-const. However, if I change the definition of the [] operator to allow for const instances, I can no longer do assignment:
// ASSUMING: const float& operator[](const unsigned i) const;
SomeClass a;
a[0] = 0; // error, because the return value of [] is a reference to const!
I really don't want to drop the const in the parameters of the == operator, since the operands don't change within the function. What is the right way to deal with this issue?
Overload operator [] to provide both:
float& operator [](unsigned int i);
float operator [](unsigned int i) const;
For a generic T that’s not cheap to copy, use a T const& return value. The general pattern for implementing read/write operator [] is
T& operator [](index_type i);
T const& operator [](index_type i) const;
I read in some sources that if we implements operator+ by operator=+ so we don't have define operator+ as "friend".
Someone can explain it?
An idea is to avoid duplicate code. See this example:
class A
{
int a = 0;
public:
A & operator+=(const A& other) { a += other.a; return *this; }
};
Then you could implement operator+ in terms of operator+= saving yourself the duplicate code, and keeping it as a free function:
A operator+(const A& lhs, const A& rhs) { A tmp(lhs); tmp += rhs; return tmp; }
Which means you now have two functions. And if you change the meaning of +=, the meaning of + changes too. Easier to maintain.
Suppose we have an operator/ on custom class:
struct my_class {
uint64_t value;
}
template<class T>
constexpr T operator/(const my_class& a, const my_class& b)
{
return static_cast<T>(a.value) / static_cast<T>(b.value);
}
How can one select a / b (where a and b are of my_class type) to return int or double, for example?
You could with a bit of template magic and conversion operators. You can first define a simple wrapper for your expression:
struct DivideMyClass {
DivideMyClass(const MyClass& lhs_, const MyClass& rhs_) : lhs{lhs_}, rhs_{rhs} {}
template<typename T>
operator T () const {
return static_cast<T>(lhs.value) / static_cast<T>(rhs.value);
}
private:
const MyClass& lhs;
const MyClass& rhs;
};
Then, overloading the operator can be done like this:
constexpr DivideMyClass operator/(const my_class& a, const my_class& b)
{
return DivideMyClass{a, b};
}
Then your code will look like this:
double d = MyClass{21} / MyClass{5}; // will be equal to 4.2
Why this solution is bad
The language is not overloading division by the return type. You code will confuse other thinking there's a bug. If you use this method extensively, you will end up in an alomost unreadable code.
Another thing, the conversion is done implicitely, and there's nothing that says if there really was a conversion done in the operator on call site.
You will prevent the AAA idom (Almost Always use Auto). auto may break your code, and it's a bad thing.
Techniques like this should be use for template expression and stuff like that. Using that for simple division will confuse other.
Can I select based on type of variable accepting the result? I.e. int
result = a/b returns int, but double result = a/b returns double?
If you are hell-bent on doing this you can, but it's complicated and I wouldn't recommend it. You have to careful weight the benefits vs the complexity introduced. You can do this via lazy evaluation:
struct X {
int value;
};
struct X_op_proxy {
const X& lhs;
const X& rhs;
template <class T>
operator T() const { return static_cast<T>(lhs.value) / static_cast<T>(rhs.value); }
};
auto operator/(const X& lhs, const X& rhs) -> X_op_proxy
{
return {lhs, rhs};
}
int main()
{
X x1{11}, x2{2};
int i = x1 / x2;
cout << i << endl;
float f = x1 / x2;
cout << f << endl;
}
This is the minimum so you can figure out what this technique is about. You can adapt it and grow it to your needs.
To choose a specific operator template, you must call it as a function:
auto result = operator/<double>(my_class{4}, my_class{2});
// result is 2.0
Is it possible to create an overload for the ostream operator that does an arithmetic operation (addition for example) and then streams out the result? The standard ostream overload that can be found all over the web can only stream from a single variable. I need something that does the following:
std::cout << x+y << std::endl;
or even more complex expressions like:
std::cout << x*y+(3*z)^2 << std::endl;
where x, y, and z are instances of a simple custom-made struct where arithmetic operations are already defined (overloaded).
EDIT:
Here is my code:
struct scalar //complex scalar data structure
{
friend scalar operator^(const scalar&, int); //integer power operator overload
friend scalar exp(const scalar&); //exponential power function
std::ostream& operator<<(std::ostream&, const scalar&)
protected:
double re;
double im;
public:
double real() {return re;} //returns the real part
double imag() {return im;} //returns the imaginary part
scalar(double _re, double _im) {re=_re;im=_im;} //constructor 1
scalar(double _re) {re=_re;im=0.0;} //constructor 2
scalar(const scalar& s): re(s.re), im(s.im) {} //copy constructor
scalar& operator=(const scalar& rhs) //assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
re=rhs.re; //sets real parts equal
im=rhs.im; //sets imaginary parts equal
return *this;
}
scalar& operator+=(const scalar& rhs) //compound addition-assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
re=re+rhs.re; //adds real parts
im=im+rhs.im; //adds imaginary parts
return *this;
}
scalar& operator*=(const scalar& rhs) //compound multiplication-assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
double x1=re; double x2=rhs.re; double y1=im; double y2=rhs.im;
re=x1*x2-y1*y2; //multiplies real parts
im=x1*y2+x2*y1; //multiplies imaginary parts
return *this;
}
scalar& operator-=(const scalar& rhs) //compound subtraction-assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
re=re-rhs.re; //adds real parts
im=im-rhs.im; //adds imaginary parts
return *this;
}
scalar& operator/=(const scalar& rhs) //compound division-assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
double x1=re; double x2=rhs.re; double y1=im; double y2=rhs.im;
double n;
n =pow(x2,2)+pow(y2,2);
if (n==0) throw(1);
re=(x1*x2+y1*y2)/n; //multiplies real parts
im=(x2*y1-x1*y2)/n; //multiplies imaginary parts
return *this;
}
const scalar operator+(const scalar& b) //addition operator overload
{
scalar c = *this;
c+=b;
return c;
}
const scalar operator*(const scalar& b) //addition operator overload
{
scalar c = *this;
c*=b;
return c;
}
const scalar operator-(const scalar& b) //addition operator overload
{
scalar c = *this;
c-=b;
return c;
}
const scalar operator/(const scalar& b) //addition operator overload
{
scalar c = *this;
c/=b;
return c;
}
};
scalar i(0.0,1.0);
scalar j(0.0,1.0);
std::ostream& operator<<(std::ostream& out, const scalar& s)
{
out << s.re << '+' << s.im << 'i';
return out;
}
scalar operator^(scalar a, int b) //integer power operator overload
{
double x=a.real(); double y=a.imag();
if (x==0) throw(1);
int r=sqrt(pow(x,2)+pow(y,2));
int arg=atan2(y,x);
scalar c(r*cos(arg),r*sin(arg));
return c;
}
scalar exp(const scalar& s) //exponential power function
{
double x=s.re; double y=s.im;
scalar c(exp(x)*cos(y),exp(x)*sin(y));
return c;
}
Here is my main function:
int main()
{
scalar x(3,4);
scalar y=2;
cout << x*y << endl;
return 0;
}
This is is the output it is supposed to give:
6+8i
And this is the errors it gives instead:
In function 'std::ostream& operator<<(std::ostream&, const scalar&)':|
error: passing 'const scalar' as 'this' argument of 'double scalar::real()'
discards qualifiers|
And if I remove the const as the compiler says, I will get the following error:
error: no match for 'operator<<' in 'std::cout << scalar::operator*(const scalar&)
(((const scalar&)((const scalar*)(& y))))'|
The << operator can't handle the full expression - and why should it?
You need to implement the separate operators (operator+, operator*, ...) for your struct, which take your structs as parameters, do the corresponding operation on it, and return another of your structs. And only then define a operator<< taking a single one of your structs.
How would you even think of passing in such a complex structure to the operator<<, let alone parse it in there? Implement the separate operators, and leave the parsing to the compiler.
e.g. for a simple struct only encapsulating an int, doing that with + operation would look like this:
struct mystruct
{
int value;
};
then define:
mystruct const operator+(mystruct const & a, mystruct const & b)
{
mystruct result;
result.value = a.value + b.value;
return result;
}
and
std::ostream & operator<<(std::ostream& out, mystruct const & a)
{
out << a.value;
return out;
}
then you can do:
mystruct a, b;
a.value = 1;
b.value = 2;
std::cout << a+b;
Edit: With your updated code, there's exactly one problem:
std::ostream& operator<<(std::ostream&, const scalar&)
should be
friend std::ostream& operator<<(std::ostream&, const scalar&);
i.e. you're missing friend and an ;
Though the error you show suggests some different problem (which jrok's answer would have a solution for) - that doesn't seem to result from compiling the code you show! So please get the shown code and error message in sync.
The error is because functions scalar::real and scalar::imag are not const - you can only call const member functions when you've got a reference to a constant scalar.
double real() const {return re;}
double imag() const {return im;}
Why don't you just write std::cout << (x+y) << std::endl;
and be done?
As long as your overloaded operator takes its argument by value:
ostream& operator<<(ostream&, Thing)
or constant reference:
ostream& operator<<(ostream&, const Thing&)
you can use it for any expression with type Thing.
You should put parentheses around complex expressions, to avoid surprises from operator precedence; in particular, the second expression involving ^ won't be parsed as you expect.
You'll only be restricted to a single variable (or, more accurately, an lvalue expression) if the operator requires a non-constant reference; so don't do that.
UPDATE Now we've seen the code, the main issue is the in-class definition of operator<< as a member function; it can't be a member. Perhaps you want it to be a friend, so it can access im and re; or perhaps you should remove the declaration (making it a non-member, non-friend), and just use the public interface. If you do that, you'll need to add const to real() and imag(), so they can be called on a const object. You should do that anyway.
(Looking at the reported error, it seems you've already changed it to use the public interface, but haven't declared the necessary functions const).
I have the following code to overload the + and += operators respectively for the class Date. The operator + was successfully overloaded, and it will take an integer n and increase Date objects by n days. This is done by applying the next_day function n times.
inline Date operator+(Date d, int n)
{
for(char j=1; j<=n; j++){
d=d.next_day(d);
}
return d;
}
inline Date operator+=(Date d, int n)
{
Date p=d+n;
return p;
}
Having overloaded the + operator, I'm using it to define the overloading of += as well. But although no errors occurred in compilation, when I use the overloaded += it doesn't seem to have any effect.
Here's my main.cpp:
#include <iostream>
#include "Date.h"
using namespace std;
int main() {
Date Initialday = Date (12,1,2012);
Initialday+=1;
cout <<"Next day = "<< Initialday <<endl;
return 0;
}
Running the main function still gives me 12/1/2012 instead of 12/2/2012. What am I doing wrong? Note: I've already overloaded << to output Date objects in a readable format, so I don't think that's the issue.
The simple fix is to take your Date object in by reference, modify it, and return it by reference. That's the expected behavior of operator+=.
inline Date& operator+=(Date &d, int n)
{
d = d + n;
return d;
}
However, to implement operator+= in terms of operator+ is backwards. It should be the other way around. operator+= should act on the members of the object, changing them directly. Then operator+ should be implemented in terms of that:
inline Date& operator+=(Date& lhs, int rhs)
{
... // code here to modify lhs directly
return lhs;
}
inline Date operator+(Date lhs, int rhs)
{
return lhs += rhs;
}
The main problem is that your += is creating a new Date object and returning it. That is the wrong semantics, plus you do not assign that return value to anything. A += operator should act on the instance it is applies to and return it by reference:
inline Date& operator+=(Date& d, int n) {
return d = d + n;
}
Usually, this would be implemented as a member function, with + implemented in terms of +=:
class Date
{
public:
Date& operator+=(int n) {
// perform whatever operation is required using
// the state of the instance.
return *this;
}
};
inline Date operator+(Date lhs, int rhs) {
return lhs += rhs; // calls member +=
}
The cleanest way would be to provide a time duration class, and implement all the operators in terms of a Date and a TimeDuration:
struct TimeDuration { .... };
class Date
{
public:
Date& operator+= (const TimeDuration& rhs) { .... }
};
inline Date operator+(Date lhs, const TimeDuration& rhs) { return lhs += rhs; }