0

I was looking at glog's documentation and got confused at the way the stream operator is being used.

LOG(INFO) << "Found " << num_cookies << " cookies";

How can it deduce that all those calls are to form a single log message?

From my understanding, this:

cout << foo << bar << baz;

is equivalent to:

cout << foo;
cout << bar;
cout << baz;

How is it able to group together the chained calls like that without a special delimiter?

EDIT:

I know that you can chain them and why is works, that was not my question. I'm asking how glog can take

LOG(INFO) << "Found " << num_cookies << " cookies";

what looks to me like 3 separate calls to the << overload and know that

"Found 3 cookies"

is a single log message as opposed to 3.

Ilia Choly
  • 18,070
  • 14
  • 92
  • 160

1 Answers1

2

cout << foo returns cout

So it then becomes
cout << bar << baz;

and so on.

Another way to see it clearer is

((cout.operator<<(foo)).operator<<(bar)).operator<<(baz);

which is exactly what is happening

You can see this from http://www.cplusplus.com/reference/ostream/ostream/operator%3C%3C/

ostream& operator<< (double val);

Edit

After the discussion, it appears that the question is more about how gLogs seperate each log into its own log entry without a terminator or any endl type object.

It appears from glancing over logging.h, that each individual log might be written by a different stream object.

#define PLOG(severity) GOOGLE_PLOG(severity, 0).stream()

This means that while using the same log object, you write to the same log entry. And every other call to Log actually creates a new stream object. RAII will take care of actually writing the finished log, as this is a temporary object and it is destroyed after the line of code is executed.

I would need to go deeper into the code to understand better but it looks like this is an accurate if brief answer. The question remains if (and if so how) this is optimized..

Community
  • 1
  • 1
Karthik T
  • 31,456
  • 5
  • 68
  • 87
  • 1
    Or, `operator<<(operator<<(operator<<(cout,foo),bar),baz)` for objects of classes which don't have istream member overloads, but rather free functions. – Benjamin Lindley Nov 26 '12 at 05:07
  • You need to manually say it is NOT the same log i am guessing. Like when using `cout`, if you do not use `endl` (or '\n`) it will end up in a line. Let me look deeper – Karthik T Nov 26 '12 at 05:12
  • @KarthikT that's what I've always thought. But glog manages to do it without a delimiter. That's the basis of the question. – Ilia Choly Nov 26 '12 at 05:14
  • I'm thinking that maybe `LOG()` creates an object which gets destroyed at the end of the chain. Then the complete result can be utilized in the destructor. – Ilia Choly Nov 26 '12 at 05:17
  • 1
    Then your question is a little miss leading. The question isnt how they are all part of 1 log, but actually how the logs are seperated at all.. – Karthik T Nov 26 '12 at 05:17
  • You are right I Think. Looking at the source code, they have lines like `#define PLOG(severity) GOOGLE_PLOG(severity, 0).stream()` which seems to indicate that the stream itself is a temporary object. So each object represents a log perhaps.. although that does sound inefficient... – Karthik T Nov 26 '12 at 05:18
  • interesting ... well if you want to edit your answer to summarize that approach I'll accept. – Ilia Choly Nov 26 '12 at 05:23