I hav been going over some old hw assignments from a class last semester.
This was a given print function to print out linked list objects.
I don't understand why the overloaded operator takes two parameters and one being an
os object. When we were printing out actual linked list objects on main.cpp, we didn't
need to pass an os object. Also, why is it returning os? Why can't we just use cout
instead of "os <<" ?
Thank you!
template <class T>
void List<T>::print(ostream & os) const
{
os << "<";
ListNode * curr = head;
while (curr != NULL) {
os << " " << curr->data;
curr = curr->next;
}
os << " >";
}
// overloaded operator<<
template <class T>
ostream & operator<<(ostream & os, const List<T> & list)
{
list.print(os);
return os;
}
By the way the question was asked and how basic it is, I'm going to try to give a very simplistic (albeit rather informal and not so pedantic) answer.
I don't understand why the overloaded operator takes two parameters
and one being an os object
operator<< is a binary operator. It has a left-hand side and a right-hand side. When you write:
cout << 123;
You are invoking this operator with two operands (arguments): 'cout' on the left and an integer, '123', on the right.
When we were printing out actual linked list objects on main.cpp, we
didn't need to pass an os object.
Your print function is a member function or operator of a class. That would implicitly deduce that the first argument, crudely speaking, does not need to be explicitly passed since you already have the 'this' pointer to work with for your list object. That's not the case with non-member operators as you don't have an implicitly deduced 'this' object to work with already for the left-hand side operand.
When you write code like this:
my_list.print(cout);
You can think of it as actually passing in two arguments, 'my_list' and 'cout'. Even though you don't write it explicitly, you have access to 'my_list' through 'this' along with its members. That's not the case if you wrote the print function as a non-member, like so:
template <class T>
void print(const List<T>& my_list, ostream& os);
That's also the case with your operator which is not a member function.
Also, why is it returning os?
Returning a reference to ostream is what allows us to write statements like this:
cout << "hello " << "world";
First we invoke operator<<(cout, "hello ") which then gives us another ostream reference to work with which then allows us to proceed to invoke operator<<(cout, "world"). If it returned void, for example, it would not allow us to invoke that operator twice in one statement since we'd be trying to output "world " with void as the left-hand operand.
Why can't we just use cout instead of "os <<" ?
cout basically implements the ostream interface. So does ofstream, ostringstream, and other types of output streams. By writing it in terms of the basic interface required and not some specific ostream derivative, you allow the code you write to work with stdio streams, file streams, stream streams, and others. Basically it makes your code very general and reusable which is something you should strive to do when practical. You'll learn about this subject more as you tackle the concept of polymorphism.
Because it is a global non-member function. With the member function version, the first parameter is implicitly the invoking object, this. That means that your class always has to be on the left hand side. With the non-member function, it's an explicit parameter; this way, you can specify any type you want, and overload operators for classes that you can't modify the source for (as long as at least one parameter is a user-defined type).
The reason why you use os is so that it works with file streams and everything (anything that inherits from ostream), instead of just cout.
It returns os so that you can do more operator<< calls on the return value. This enables operator chaining, like w << x << y << z, which is the same as operator<<(operator<<(operator<<(w, x), y), z). If you return void or something, you would have to stop at w << x because you can't do anything with the return value of void.
I don't understand why the overloaded operator takes two parameters and one being an os object. When we were printing out actual linked list objects on main.cpp, we didn't need to pass an os object.
Yes you did: when you say cout << x, you are passing cout and x to operator<<.
Also, why is it returning os?
To make cout << x << y possible. This is parsed as (cout << x) << y, i.e. it inserts y into the return value of cout << x.
Why can't we just use cout instead of "os <<" ?
Because sometimes you want to output to another stream than standard output.
When we were printing out actual linked list objects on main.cpp, we
didn't need to pass an os object.
Yes, you did.. something like cout << obj;, where cout is the os output stream.
Also, why is it returning os? Why can't we just use cout instead of "os <<" ?
This allows chaining: cout << obj << " " << obj2;
Why can't we just use cout instead of "os <<" ?
That would hard-wire the output stream, so you couldn't write to file or any other output.
Related
I am curious if std::cout has a return value, because when I do this:
cout << cout << "";
some hexa code is printed. What's the meaning of this printed value?
Because the operands of cout << cout are user-defined types, the expression is effectively a function call. The compiler must find the best operator<< that matches the operands, which in this case are both of type std::ostream.
There are many candidate operator overloads from which to choose, but I'll just describe the one that ends up getting selected, following the usual overload resolution process.
std::ostream has a conversion operator that allows conversion to void*. This is used to enable testing the state of the stream as a boolean condition (i.e., it allows if (cout) to work).
The right-hand operand expression cout is implicitly converted to void const* using this conversion operator, then the operator<< overload that takes an ostream& and a void const* is called to write this pointer value.
Note that the actual value resulting from the ostream to void* conversion is unspecified. The specification only mandates that if the stream is in a bad state, a null pointer is returned, otherwise a non-null pointer is returned.
The operator<< overloads for stream insertion do have a return value: they return the stream that was provided as an operand. This is what allows chaining of insertion operations (and for input streams, extraction operations using >>).
cout does not have a return value. cout is an object of type ostream. operator << has a return value, it returns a reference to cout.
See http://www.cplusplus.com/reference/iostream/ostream/operator%3C%3C/ for reference.
The only signature that matches is:
ostream& operator<< (ostream& ( *pf )(ostream&));
so it returns the pointer to the operator<< member.
the one in James' answer. :)
I believe that would be the address of the ostream object that "" got printed to
I'm trying to write my own stream class. It will do something with the input and pass it on to std::cout. So far I passed functions operating on the stream (e.g. std::endl) on to cout. Now, I want to check for std::endl input and perform some actions, if it occurs. I have implemented the behaviour like this
DebugStream& DebugStream::operator<< (ostream& (*pfun)(ostream&))
{
if(pfun == std::endl)
{
// do something
}
pfun(cout);
return *this;
}
Which results into
/path/to/file.cpp:89:24: error: assuming cast to type ‘std::basic_ostream<char>& (*)(std::basic_ostream<char>&)’ from overloaded function [-fpermissive]
using the GCC compiler. I don't know, how to compare the function pointer against the std::endl function. Maybe this problem is related to the template nature of the std::endl function? Or because it's inline?
The reason you get a warning is that std::endl is a template function. You can fix this error by forcing a comparison to a template instance of a particular type through a cast, like this:
typedef ostream& (*io_manip_ptr_t)(ostream&);
void demo(io_manip_ptr_t pfun) {
if (pfun == (io_manip_ptr_t)&endl) {
cout << "Hi" << endl;
}
}
Demo.
Note: Even though the work-around is available, this is only a workaround, not a solid solution, because comparing function pointers to decide on functionality introduces a very serious problem: your functions get reduced to an enum, so your code becomes impossible to extend from the outside.
void main() {
cout << "Hello World" << endl;
}
I'm not allowed to make any change to the above main function while the output on the screen need to be sth like:
initialize
Hello World
clean up
My thought is that I need to use overloading operator of << . However I need to know what's the data type of the double quoted string following the operator << , otherwise I will not make full use of my redefined << operator. Anyone any thought?
The type of the literal is "array of {suitable number of} const chars", but a better approach might be to have some kind of global object.
(Adding an overload for the array would probably not even work, because the existing overload for char const * would be getting in the way.)
You could redefine std::ostream& operator<< (std::ostream&, const char*). There's one huge problem with this approach: It is undefined behavior. The standard library already defines that function, and you are not allowed to redefine standard library functions.
The key to solving this problem is to recognize that cout is in the global namespace. The solution is simple: Write your own class that overloads operator<< and make a global variable named cout that is an instance of this class. That way you are not running into undefined behavior.
You'll also need to do something with that endl that is in the global namespace.
Your code should look something like
// Insert your code here.
int main () {
cout << "Hello World" << endl;
}
Since this looks like homework, I'll leave the rest up to you.
The type of a string literal is char const[n] where n is the number of characters in the string literal, including the terminating null character. Note, however, that the solution to your problem isn't overloading operator<<(). Instead, you should look at constructors, destructors, and variable with static live-time.
I am learning operator overloading. "out" is being used instead of "cout" when overloading "<<" operator. I don't understand why.
ostream &operator<<( ostream &out, const IntList &L ) {
out << "[ ";
for (int k=0; k< L.numItems; k++) {
out << L.Items[k] << ' ';
}
out << ']';
}
I want to ask differences between cout and out and what happens if I use cout instead of out.
Thanks for answers.
What you are looking at is a overloaded "stream insertion" operator, allowing some custom class to be written to an ostream object using the typical cout << myObject syntax.
The variable in this case is called out because that's the name they've given to the ostream object being passed into the function, which may be any output stream, whether it's cout or an fstream or a stringstream. It's just a variable name, and they could have called it blah and written:
ostream &operator<<( ostream &blah, const IntList &L ) {
blah << "[ ";
// ...
}
Typically you choose a variable name which is descriptive, and out as a name for an output stream is pretty descriptive.
cout would be an especially bad variable name, as it is strongly associated with std::cout, used for writing specifically to the standard output stream. This code doesn't write specificially to standard output, it writes to any ostream object via the << operator so they've chosen a more generic name for their ostream argument.
I want to ask differences between cout and out and what happens if I use cout instead of out. Thanks for answers.
In this case, an ostream& (out) is a parameter passed to the function. This allows the operator<< to work on any ostream.
cout is a specific ostream instance - the standard output stream. If they used cout here, you wouldn't be able to use the << operator on cerr (the standard error stream) or any other ostream. If you replaced the out with cout in the body, any time you used this on a different ostream, it'd be written to cout. (Of course, if you changed the parameter to be named cout, that wouldn't happen - but it would be very misleading to anybody looking at this code, as people would expect that the code writes to the standard output stream, not to the stream being passed in.)
In general, you only would want to use cout as a name if you are specifically referring to std::cout - the standard output stream, as using it in other contexts would be very confusing.
out is the name of the ostream object passed to the overloaded operator (inside the implementation of the operator).
The overloaded operator allows you to write code like this
IntList i;
cout<<i;
or
cerr<<i;
In the implementation if you substituted out with cout, then the second call
cerr<<i;
would print to standard output whereas it should have printed to standard error.
The critical thing here is really the types in the function signature: as long as it's a freestanding function with two parameters - one of type std::ostream& and the other able to be matched by the value to be streamed, then the function body will be invoked. It should return a reference to the stream to allow chaining (as in if (cout << firstIntList << secondIntList)).
The actual parameter names are whatever you feel like, as long as they're not reserved words. I tend to use "os", as in output-stream.
Here is what troubles me: I have an overloaded operator << in a header file FAPPDebug.h such as:
QTextStream& operator << (QTextStream& a, FAPPDebug& b);
and the implementation in FAPPDebug.cpp:
QTextStream& operator << (QTextStream& a, FAPPDebug& b)
{
QString msg = *b.stream->ts.string(); // just take the message from b
a << msg;
return a;
}
and the corresponding function call:
QTextStream(stdout) << (debug() << "Quitting because application object is not set.");
regardless of how weird this looks, this compiles (and works!) under Windows with MSVC2010
debug() is just a macro to create a FAPPDebug object from the current location. Please note the extra set of () around (debug() << "...") without that it is not producing what I want.
On the other end under Linux with g++ 4.4 I get the following error:
MessageBroker.cpp:91: error: no match for ‘operator<<’ in
‘QTextStream(stdout,
QFlags((QIODevice::OpenModeFlag)3u)) <<
((FAPPDebug*)((FAPPDebug*)FAPPDebug(417, ((const
char*)"MessageBroker.cpp"), ((const char*)(& PRETTY_FUNCTION)),
(LogLevel)7u).FAPPDebug::operator<<(((const
char*)"Module")))->FAPPDebug::operator<<(((const QString&)((const
QString*)(&
ModuleBase::getModuleDescription()())))))->FAPPDebug::operator<<(((const
char*)"Quitting because application object is not set."))’
/usr/local/Trolltech/Qt-4.8.2/include/QtCore/qtextstream.h:184: note:
candidates are: FAPPDebug.h:94: note: QTextStream&
operator<<(QTextStream&, FAPPDebug&)
(There are a lot of candidates, I have just kept what is important)
I have modified the function call to be:
::operator << (QTextStream(stdout), debug() << "Failed to schedule application startup.");
and I get the error message:
MessageBroker.cpp: In member function ‘bool
MessageBroker::init(Application*, const QString&)’:
MessageBroker.cpp:91: error: no matching function for call to
‘operator<<(QTextStream, FAPPDebug&)’
/usr/local/Trolltech/Qt-4.8.2/include/QtCore/qchar.h:396: note:
candidates are: QDataStream& operator<<(QDataStream&, const QChar&)
/home/ferenc/work/trunk/Core/Common/FAPPDebug.h:94: note:
QTextStream& operator<<(QTextStream&, FAPPDebug&)
so as you can see the correct function is found every time (yes, the FAPPDebug.h header is included in MessageBroker.cpp), but the "more standard compliant" compiler failed to use it. I have the feeling that this is a glitch in my comprehension of the standard somewhere, so I am asking for your help to find it.
EDIT: the operator is declared as friend in class FAPPDebug
EDIT2: The debug() is a macro, and is defined like:
#define debug() FAPPDebug(__LINE__, __FILE__, __PRETTY_FUNCTION__, LOG_DEBUG)
ie. it just created a FAPPDebug object with parameters indicating the current position.
Thanks!
f.
I think the problem may be that your insertion operator accepts a reference (lvalue) as the first parameter, as expected, but you are trying to pass a rvalue created automatically from a constructor. Think about it, how do you expect an automatically created QTextStream(stdout) to live a sequence of calls of the type, QTextStream(stdout) << a << b << c. In truth, this is x << a then x << b then x << c. For it to live that happening in a single sentence I think both the first and the return must be const references, which is able to pin your rvalue.
Or you may just declare a variable like QTextStream qout(stdout), and use qout instead.
Shouldn't the second parameter to your operator<< be FAPPDebug
const&? You can't initialize a non-const reference with a temporary,
even if some compilers still fail to detect the error.
If you look closely, the functions which compiler see used and what you have defined aren't the same.
What it sees:
no matching function for call to ‘operator<<(QTextStream, ...
What it has defined
QTextStream& operator<<(QTextStream&, ...
It seems like temporary object couldn't be passed as non-const reference.
So either change it to QTextStream const& or use rvalue reference.
EDIT: Oh well, I just understood that stream passed as first parameter can't really be const. Using rvalue reference or just catching by value, if it's possible, seems to me the only way to do it now. It's your (debug() ...) object that's causing the problem.
I had this problem, and it is a problem of any beginner in C++.
QTextStream& operator << (QTextStream& a, FAPPDebug& b);
This is your declaration, but your usage is:
QTextStream(stdout) << (debug() << "Quitting because application object is not set.");
I assume you have your FAPPDEbug object having an operator that lets it use operator on const char pointer. so then this becomes this
QTextStream(stdout) << FAPPDebugObject;
And you compiler wont find it in a case if FAPPDebugObject was not returned as a reference, because you are asking for a reference arg in the next operator.
I hope it made sense to you, or anyone looking for a solution.