Which << is my overloaded operator in this statement? - c++

I have an overloaded << operator from my reckful class implemented as follows:
ostream& operator << (ostream& os, const reckful& p)
{
os << p.PrintStuff();
return os;
}
PrintStuff() just being a member function of reckful that returns a string.
The way I understand things, if I were to write something like cout << reckobject << endl; in main(), cout << reckobject would take precedence and my overloaded << (using cout as the left operand and reckobject as the right operand) would return the ostream object os, leaving the expression os << endl; to be evaluated which would output the string and then end the line. So, the first << is the one I declared and the second is the standard << right?
However, my main question is... what is the sequence of events, which are the left and right operands, and which << operators are which when I run a statement like this:
cout << "reckful object = " << reckobject << "!" << endl;
Why does this work if there isn't an ostream object and a reckful object on either side of one << ?
Thanks.

If you notice standard way to implement << it returns the ostream itself. This is the critical piece
So something like
cout << "reckful object = " << reckobject << "!" << endl;
will be called once for
cout << "reckful object = "
This function call will return a ostream with which the second call will be made
namely
cout << reckobject;
so on an so forth.
You can test is out by implementing your << as
void operator << (ostream& os, const reckful& p)
{
os << 1;
}
in which case you can do
std::cout << p;
but not
std::cout << p << std::endl;
The operators make it harder to understand but consider this Point class
struct Point
{
Point& setX( int x) { X = x; return *this;}
Point& setY( int y) { Y = y; return *this;}
int X;
int Y;
};
The way setX and setY are defined, allows
Point p;
p.setX( 2 ).setY( 4 );
This is the same mechanism << is using to chain function calls.

Because each << returns a reference to cout. Because the operator << is left-associative, the calls are done from left to right, so
a << b << c
is equivalent to
(a << b) << c
which is equivalent1 to
operator<<(operator<<(a, b), c);
So in your example, you are doing
operator<<(operator<<(operator<<(operator<<(cout, "reckful object = "), reckobject), "!"), endl);
As you can see, each << depends on the return value of the previous << (or just cout in case there is no further left <<). If you change one of the return types of the <<s to void, you effectively stop any more << calls, because void can't be used as an argument to a function.
1 It's not exactly equivalent because in that example, all operator<< are free functions, whereas in reality, some can be member functions, so you could have a mix of member and non-member calls like
operator<<(a, b).operator<<(c);
or
operator<<(a.operator<<(b), c);

Related

How does C++ compiler find closest type conversion when displaying my class object?

I write a class Fraction, and would like to display Fraction object with std::cout:
Fraction f(3, 5);
std::cout << f << std::endl;
I know overloading operator << can be used for this display purpose. But I can also overload operator type() function, and when only with operator double()(let type be double), I can still std::cout << f << std::endl.
Even more, I can also implement operator std::string(). But, when the mentioned 3 overloaded operator functions all exist, without explicitly type conversion, which one is called when doing std::cout << f << std::endl ? This really makes me curious, is this undefined behavior denpending on compiler implementation, or if there is some rule for scoring the closest/most suitable function to call?
To reproduce, use the following code:
#include <iostream>
#include <string>
class Fraction
{
public:
Fraction(int num, int den=1):
numerator(num), denominator(den) {}
operator double() const {
std::cout << "[operator double()]";
return numerator*1.0 / denominator;
}
operator std::string() const {
std::cout << "[operator std::string()]";
return std::to_string(numerator) + "/" + std::to_string(denominator);
}
private:
int numerator;
int denominator;
#ifdef OVERLOAD_STREAM_OP
friend std::ostream& operator << (std::ostream& os, const Fraction& frac);
#endif
};
#ifdef OVERLOAD_STREAM_OP
std::ostream& operator << (std::ostream& os, const Fraction& frac)
{
std::cout << "[operator <<]";
os << std::to_string(frac.numerator) << "/" << std::to_string(frac.denominator);
return os;
}
#endif
int main()
{
Fraction f(3, 5);
double d = 4 + f;
std::cout << "\n--- now let's print\n";
std::cout << "f: " << f << std::endl;
std::cout << "f: " << std::string(f) << std::endl;
std::cout << d << std::endl;
return 0;
}
The output on my ubuntu 20.04:
(base) zz#home% clang++ fraction.cpp
(base) zz#home% ./a.out
[operator double()]
--- now let's print
f: [operator double()]0.6
f: [operator std::string()]3/5
4.6

operator << of enum type uses the overloaded operator or not?

I hope this time my question is better formulated and formatted.
Here's the code that produces two separate outputs when I think it should not since I use everytime (I think) the overloaded operator<< for an enum type.
#include <iostream>
using namespace std;
enum Etat { Intact = 5 };
class Ship {
public:
Etat etat_;
Ship ( Etat t = Intact) : etat_(t) {}
~ Ship() {}
ostream& description ( ) const { return cout << "Etat: " << etat_ << " --- ";}
//---------------------------------------ˆˆˆˆ----
};
ostream& operator<< ( ostream& s, const Etat& etat_ )
{
switch ( etat_ )
{
case Intact: s << "intact"; break;
default: s << "unknown state";
}
return s;
}
ostream& operator<< ( ostream& s, Ship n ) { return s << "Etat: " << n.etat_ ; }
int main()
{
Etat etat_ = Intact;
cout << endl << endl << "Etat: "
<< etat_ << " \"cout << etat_\"" << endl << endl;
cout << Ship(etat_)
<< " \"cout << Ship(etat_)\"" << endl << endl;
cout << Ship(etat_).description()
<< " \"cout << Ship(etat_).description()\"" << endl << endl;
return 0;
}
This is what I get in the terminal:
Etat: intact "cout << etat_"
Etat: intact "cout << Ship(etat_)"
Etat: 5 --- 1 "cout << Ship(etat_).description()"
Can anyone explain to me why, in the last case, not only it takes the integer value of the enum attribut, but also adds a "1" after the test string " --- "???
The only thing I can think of is because I used an unorthodox return method in description(), ie 'return cout << ..", but it seems to work since the test string appears.
Is there a way to force the use of the operator<< overload in description()?
Thanks
In the description() function you are returning a reference to std::cout and use it in the std::cout call in main function. There is a reason why operator<< takes an ostream reference as it's first argument. You should modify your function like this and all should work:
ostream& description(ostream& os) const {
return os << "Etat: " << etat_ << " --- ";
}
The random "1" printed out there is caused likely due to the ostream in your example trying to print out reference to itself.

C++ ostream << overloading problems

We know that the fascinating class iostream is something too powerful.
it has overloded the insertion operator "<<" to take many datatypes:
ostream& operator(ostream&, int),
ostream& operator(ostream&, char)...
we cannot instantiaate ostream: ostream print;
because ostream because its most CTORSs are "protected-socoped" (cannot be accessed from outside).
the only Constructor we can call is ostream(streambuf*) which takes a pointer to another class object ( class streambuf);
I just wanted to mess up with this class:
#include <ostream>
using namespace std;
int operator << (ostream& out, int* x)
{
out << "invoked!" << endl;
cout << *x; // works well!
cout << x; // normally works well and it prints the address that x points to but instead the program get in infinite loop or crushes!
return *x;
}
int main()
{
system("color 1f");
int* pVal = new int(57);
cout << *pVal << endl;
int* pX = new int(7);
cout << *pX << endl;
cout << *pVal << ", " << *pX << endl;
//cout << pVal << endl; // this doesn't work because my operator returns
//int and not a reference to ostream.
// and it is equal to: 0 << endl; which generates the same error
cout << pVal; // this works
// cout << endl << endl << endl;
return 0;
}
I overloaded the insertion operator to take an lvalue as a reference to an ostream object and a pointer to int as rvalue, I popup a message inside my function to get sure that it is invoked.
Note that I intentionally overloaded it to return int value so that no one can write:
out << pInt << *pInt << endl;
... but just:
out << pInt;
My problem, as you can see in the inline-comments above, is that whilst cout << x normally works well, instead the program get in infinite loop or crushes!
return *x;
Can anyone explain why I am getting the error?
The problem hapens because if you just cout << x, it will call your overloaded function over and over. It never returns.
Here's the solution (cast x to void*)
int operator << (ostream& out, int* x)
{
out << "invoked!" << endl;
cout << *x; // works well!
cout << (void*)x;
return *x;
}

How to make the left operand of the operator << a function?

void operator<< (const Integer& left, const Integer& right)
{
cout << "\n: " << right.i;
}
can be accessed like:
Integer obj;
obj << 5 << 3 << 2;
Fine:
But qDebug works like qdebug() << 2;
Which means that the left operand of << operator is a function.
What should be the syntax of a user defined function so that I can write:
myfunc() << 2;
The left operand is not a function, it is the value the function returns. Specifically, qDebug() returns an instance of QDebug, which has some 20 overloads of << defined.

Using operator overloading in C++

class A
{
public:
ostream& operator<<(int string)
{
cout << "In Overloaded function1\n";
cout << string << endl;
}
};
main()
{
int temp1 = 5;
char str = 'c';
float p= 2.22;
A a;
(a<<temp1);
(a<<str);
(a<<p);
(a<<"value of p=" << 5);
}
I want the output to be: value of p=5
What changes should is do...and the function should accept all data type that is passed
There are 2 solutions.
First solution is to make it a template.
template <typename T>
ostream& operator<<(const T& input) const
{
cout << "In Overloaded function1\n";
return (cout << input << endl);
}
However, this will make the a << str and a << p print c and 2.22, which is different from your original code. that output 99 and 2.
The second solution is simply add an overloaded function for const char*:
ostream& operator<<(int string)
{
cout << "In Overloaded function1\n";
return (cout << string << endl);
}
ostream& operator<<(const char* string)
{
cout << "In Overloaded function1\n";
return (cout << string << endl);
}
This allows C strings and everything convertible to int to be A <<'ed, but that's all — it won't "accept all data type that is passed".
BTW, you have forgotten to return the ostream.