c++ overload "<<" doesn't work for output "obja + objb" - c++

I overload "<<" and "+" operators for my class. It works fine if I output single object using cout<<a;. But it fails when I output cout<<a+b;
g++ version: g++ (GCC) 9.2.0
class UTF8string{
private:
string data;
public:
UTF8string();
UTF8string(string a);
int bytes();
int find(string a);
int length();
void replace(string a, string b);
UTF8string operator+(UTF8string &a);
UTF8string operator*(int a);
UTF8string operator+=(const UTF8string& rhs){
data.append(rhs.data);
return *this;
}
friend UTF8string operator!(UTF8string &a);
friend std::ostream& operator<<(std::ostream& os, UTF8string &a);
friend UTF8string operator+(int a, UTF8string &other );
};
std::ostream& operator<<(std::ostream& os, UTF8string &a){
os << a.data;
return os;
}
UTF8string UTF8string::operator+(UTF8string &a){
string b = data ;
return UTF8string(b.append(a.data));
}
my test code:
cout << "test + test2: " << test + test2 << endl; // doesn't work
cout << "test contains: " << test << endl; // works well
Error
testUTF8string.cpp:38:38: 错误:cannot bind non-const lvalue reference of type ‘UTF8string&’ to an rvalue of type ‘UTF8string’
38 | cout << "test + test2: " << test + test2 << endl;
| ~~~~~^~~~~~~

You're using references-to-non-const throughout.
That is a bad idea.
If you don't need to modify the object through a reference, the reference should be to const.
If your reference is not to const, temporaries cannot bind to it.
The return-by-value result of your operator+ is a temporary.

Result of your overloaded operator+ in test + test2 is temporary value. Temporary value cannot be passed to function by non-const reference.
It can be fixed by using const reference:
std::ostream& operator<<(std::ostream& os, const UTF8string &a){
os << a.data;
return os;
}
UTF8string UTF8string::operator+(const UTF8string &a){
string b = data ;
return UTF8string(b.append(a.data));
}
It is good practice to always use const references when passing arguments which are meant to be read-only.

Apart from the solution what #Lightness Races with Monica have suggested you can also overload the operator << for rvalue references like:-
friend std::ostream& operator<<(std::ostream& os, const UTF8string &&a);
It is sometimes useful to overload like this when moving is cheaper then copying.
Or for some reason you want a different implementation in two cases.
NOTE: In case of operator << it doesn't make sense to do the oveloading as the data/object being passed to stream should be const

Related

<< overload operator, why it can't return to just class type(without reference)

so this is a classic cout overloading friend member function. I have a simple question here. why it has to be return to the reference(ostream&)?. Why can't it be return to just ostream?
class Time {
private:
int hours;
int minutes;
public: friend ostream& operator<<(std::ostream &os, const Time& t) { os<<t.hours<< "hours, " <<t.minutes<< "minutes;
return os; //why it can't return to just ostream(witout reference &)
}
That should be:
friend std::ostream &operator<<(std::ostream &os, const Time& t) {
os << t.hours << "hours, " << t.minutes << "minutes;
return os;
}
That must be a reference because you can't copy an ostream object. What would this mean, copying the underlying file? No, no copy.
ostream objects are not copyable. Since they represent 'real world` resources, (consoles and files etc) it doesn't make any sense to copy them.
So because they are not copyable they have to be passed around by reference, so the correct return type from operator<< is a reference, ostream&.

C++ How do I print an object?

I have created a constructor
Location(double xIn,double yIn,string placeIn,int timeIn)
: x(xIn),y(yIn) ...so on {
Say I want to print Location home(x,y,place,time); that's in the main().
How would I do so? I've been searching around and was told to use operator<<. How would I implement this?
UPDATE: After creating some get methods and I tried doing,can't exactly compile it because of the problem
ostream &operator<<(ostream & o, const Location & rhs){
o << rhs.getX() << "," << rhs.getY() << "," << rhs.getPlace() << "," << rhs.getTime();
return o; }
Here is the stencil for overloading operator<<:
class Any
{
public:
friend std::ostream& operator<<(std::ostream& output, const Any& a);
private:
int member;
};
std::ostream&
operator<<(std::ostream& output, const Any& a)
{
output << a.member;
return output;
}
This one possible stencil, there are other possibilities. Search the internet for "c++ stream insertion operator overload example" for other implementations.

C++ operator I/O overloading

I've encountered a strange problem while overloading << operator for a Complex class (The Complex class and overload function are not complete, but the meaning should be the same - BUT if you feel there is missing some important part, just prompt me ;-) ):
class Complex {
float m_fReal;
float m_fImaginary;
public:
Complex();
Complex(float real, float imaginary);
Complex add(Complex) const;
friend std::ostream& operator<<
(std::ostream& out, Complex cComplex);
};
Overload function:
std::ostream& operator<<(std::ostream& out, Complex cComplex) {
out << cComplex.m_fReal << " " << cComplex.m_fImaginary;
return out;
}
Add function:
Complex Complex::add(Complex cComplex) const {
return Complex (m_fReal + cComplex.m_fReal,
m_fImaginary + cComplex.m_fImaginary);
}
Function call in main:
Complex x(1,1), y(2,2);
cout << "x+y=" << x.add(y) << endl;
While the above works, this does not (only parts that differ).
Declaration in Complex class:
friend std::ostream& operator<<
(std::ostream& out, Complex& cComplex);
Definition:
std::ostream& operator<<(std::ostream& out, Complex& cComplex) {
out << cComplex.m_fReal << " " << cComplex.m_fImaginary;
return out;
}
My intention was to pass the Complex class by reference. Can anybody explain to me, what went wrong in this code and why?
You need to accept the object to output by const reference. You're accepting it as a non-const reference to which the return from add cannot be bound.
std::ostream& operator<<(std::ostream& out, const Complex& cComplex) {
This design/behavior is to prevent mistakes where a function expects to mutate the value of a reference parameter, but the reference has been bound to an unnamed temporary object, in other words memory that can't be accessed again, rendering the changes pointless.
Your definition should be
std::ostream& operator<<(std::ostream& out, const Complex& cComplex) {
out << cComplex.m_fReal << " " << cComplex.m_fImaginary;
return out;
}
cComplex needs to be const qualified for you to access its private variables using "."

Cascading overloaded cout operator error `No match` when used with other overloaded operators

I have overloaded << in my code as a friend function. Even after using braces while cascading there is still the error
error: no match for ‘operator<<’ in ‘std::operator<< [with _Traits =
std::char_traits<char>]((* & std::cout), ((const char*)"complex conjugate is "))
<< c.myComplex::operator~()’
I have a class myComplex
class myComplex
{
private:
float real;
float imaginary;
public:
myComplex();
myComplex(float a,float b);
friend std::ostream& operator<<(std::ostream& iso,myComplex& a);
myComplex operator~() const;
};
The overload for <<, ~and the constructors are as follows,
std::ostream& operator<<(std::ostream& oso,myComplex& a)
{
oso<<a.real<<" + "<<a.imaginary<<"i"<<std::endl;
return oso;
}
myComplex myComplex::operator~() const
{
return myComplex(this->real,-1*this->imaginary);
}
myComplex::myComplex(float a,float b)
{
real = a;
imaginary = b;
}
I use it in main as follows,
Line 1: std::cout << "c is " << c << "\n";
Line 2: std::cout << "a is " << a << "\n";
Line 3: ((std::cout <<"complex conjugate is ")<<(~c))<<"\n";
Line 3: std::cout <<"complex conjugate is "<<~c<<"\n";
Line 1 and 2 work fine, but Line 3 gives the error. If it can cascade for Line 1 and 2 and since ~c also returns an ostream why does it give an error for that?
A temporary object (in this case that returned by operator~()) cannot be bound to a non-const reference. Change argument of operator<<() to be a const reference:
friend std::ostream& operator<<(std::ostream& iso,myComplex const& a);
Because your operator~() returns by value, you are feeding a temporary object into your ostream& operator<< here:
std::cout <<"complex conjugate is "<< ~c <<"\n";
// ^^ HERE! Temporary myComplex value.
The operator takes its 2nd argument by non-const reference myComplex&. A non-const reference cannot bind to a temporary. Change it to
std::ostream& operator<<(std::ostream& oso, const myComplex& a);
Use const myComplex & instead of myComplex &:
friend std::ostream& operator<<(std::ostream& iso, const myComplex& a);
^^^^^
And change the implementation, of course.
Your operator << takes the second parameter by non-const reference, which means it can't bind to a temporary (such as the one returned by ~). Change operator << to accept const myComplex& as the second argument.
It would certainly be weird if the stream-output operator modified its argument anyway.
BTW, do you know that C++ has a built-in class std::complex?

no return statement in friend class

The warning is being generated by the ostream & operator<<(ostream &os, A &A0) function.
Here's how the class's defined:
class A
{
public:
friend ostream & operator<<(ostream &os, A &A0);
A& operator=(string strSlot_);
A& operator+(string strSlot_);
A& operator+(const A &B);
A& operator=(const A &B);
string slotReturn();
A(string strSlot_);
A(const A &object);
void slotChange();
void sCout();
~A();
A();
private:
string strSlot;
int n;
};
ostream & operator<<(ostream &os, A &A0)
{
os << "strSlot = \"" << A0.slotReturn() << "\"" << endl;
}
string A::slotReturn()
{
return strSlot;
}
The question is, what is it supposed to return? *this doesn't seem to work (because it's a friend?). (It's merely a warning, but still, I just want to know.)
Also, why can't I pass A &A0 as a const (in which case the error is: "passing 'const A' as 'this' argument of 'std::string A::slotReturn()' discards qualifiers")?
You need to return the std::ostream& itself:
ostream & operator<<(ostream &os, A &A0)
{
return os << "strSlot = \"" << A0.slotReturn() << "\"" << endl;
}
As an aside, the terminology is slightly off. There is no "friend class". The std::ostream& operator<< is the friend here. But it doesn't even need to be a friend, because it just calls a public member function of A. So you can remove the friend declaration.
You should probably also make slotReturn() a const method:
string slotReturn() const;
// ^ const method
and modify the ostream& operator<< to take a const reference:
ostream & operator<<(ostream& os, const A& A0) { .... }
This will allow you to print out temporaries:
std::cout << A("I am a temporary!") << "\n";