By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,171 Members | 1,004 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,171 IT Pros & Developers. It's quick & easy.

Help with operator overloading of <<

P: n/a
Hi,
I'm trying to play with classes and I'm having trouble with a
theoretical
problem.

I've create a 'Log' class, who creates and writes to log files. I was
able
to overload the << operator so that I could write to my log as follows:

Log logOne("log.txt", true, "\n" );
logOne<<"BLAH"<<"BLAH2";

In the constructor, the 'true' refers to having the log class write out
a
datetime stamp of each log entry, while the '\n' indicates how to
terminate
the log line.

The problem is that when I use the syntax about (<<"A"<<"B" ), etc, it
ends
up writing multiple lines because the << function is getting called
each
time. What I would like to do is have A and B be concatenated into one
string and then do the actual call to write the log line once. How do I
know
if I am the 'LAST' item being sent to the << so that I can store the
intermediate values and not write it out unless I am last?

Here is my function: (quite simple)
Log & operator << (string a)
{
writeLog(a);
return *this;
}
Thanks in advance...

Jul 23 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a

"winbatch" <ho********@gmail.com> wrote in message
news:11*********************@o13g2000cwo.googlegro ups.com...
Hi,
I'm trying to play with classes and I'm having trouble with a
theoretical
problem.

I've create a 'Log' class, who creates and writes to log files. I was
able
to overload the << operator so that I could write to my log as follows:

Log logOne("log.txt", true, "\n" );
logOne<<"BLAH"<<"BLAH2";

In the constructor, the 'true' refers to having the log class write out
a
datetime stamp of each log entry, while the '\n' indicates how to
terminate
the log line.

The problem is that when I use the syntax about (<<"A"<<"B" ), etc, it
ends
up writing multiple lines because the << function is getting called
each
time.
Operator << must (!) be called here twice because you call it twice ;-) So
that behavior absolutely makes sense.
What I would like to do is have A and B be concatenated into one
string and then do the actual call to write the log line once. How do I
know
if I am the 'LAST' item being sent to the << so that I can store the
intermediate values and not write it out unless I am last?

Here is my function: (quite simple)
Log & operator << (string a)
{
writeLog(a);
return *this;
}


Without seeing the writeLog(a) function this code snippet is not worth very
much, but there are some things that are visible right away. First of all
you should pass a const string reference instead of the string object. This
has nothing to do with your problem but youŽll save yourself unnecessary
copies of the string object.
Despite this your problem is located in the writeLog function which I assume
will look something like this:

void writeLog( string Text ) {
cout << m_Date << " " << Text << endl;
}

And here it is - the end of line manipulator endl. Just skip it and all
strings are going to be output on the same line. However, you should
terminate the line yourself sending the endl or "\n" to the stream after the
last thing you want to output. In principle it works just like the normal
cout stream.

Cheers
Chris
Jul 23 '05 #2

P: n/a
Chris,

I don't have an endl in my writeLog function. The reason is that the
constructor takes a parameter which will be the EOL for the log. The reason
for this is that I have another class which contains multiple logs and I
just send it a string and it will call the writeLog of each of the Log
objects inside. Since certain logs will have different terminators, I
didn't want to have to deal with this when I passed the string to be logged,
but rather it be part of the Log object itself.

I realize that the << is being called twice, and that's exactly the problem.
I only want the log to be written to the file when I'm on the LAST call to
the <<. All previous calls should simply append the string to some buffer
so that when I hit the last call to <<, I can write out my buffer (with the
last string included).

This is the writeLog function for your reference. Regarding your advice
about const, I have taken your advice.

void Log::writeLog( const string &logLine )
{
content=logLine;
if ( !out->is_open() )
throw DHException( 3, "Attempt to write to log file [", fileName.c_str(),
"] without opening first!");

if ( includeDate )
{
current.now();
content = Date::getFormattedDate( current ) +">" + content + suffix;
}
out->write( content.c_str(), content.size() );
out->flush();

if ( !out->is_open() )
throw DHException ( 3, "Could not write to log file [", fileName.c_str(),
"] !");

}

"Chris Theis" <Ch*********@nospam.cern.ch> wrote in message
news:cu**********@sunnews.cern.ch...

"winbatch" <ho********@gmail.com> wrote in message
news:11*********************@o13g2000cwo.googlegro ups.com...
Hi,
I'm trying to play with classes and I'm having trouble with a
theoretical
problem.

I've create a 'Log' class, who creates and writes to log files. I was
able
to overload the << operator so that I could write to my log as follows:

Log logOne("log.txt", true, "\n" );
logOne<<"BLAH"<<"BLAH2";

In the constructor, the 'true' refers to having the log class write out
a
datetime stamp of each log entry, while the '\n' indicates how to
terminate
the log line.

The problem is that when I use the syntax about (<<"A"<<"B" ), etc, it
ends
up writing multiple lines because the << function is getting called
each
time.


Operator << must (!) be called here twice because you call it twice ;-) So
that behavior absolutely makes sense.
What I would like to do is have A and B be concatenated into one
string and then do the actual call to write the log line once. How do I
know
if I am the 'LAST' item being sent to the << so that I can store the
intermediate values and not write it out unless I am last?

Here is my function: (quite simple)
Log & operator << (string a)
{
writeLog(a);
return *this;
}


Without seeing the writeLog(a) function this code snippet is not worth
very
much, but there are some things that are visible right away. First of all
you should pass a const string reference instead of the string object.
This
has nothing to do with your problem but youŽll save yourself unnecessary
copies of the string object.
Despite this your problem is located in the writeLog function which I
assume
will look something like this:

void writeLog( string Text ) {
cout << m_Date << " " << Text << endl;
}

And here it is - the end of line manipulator endl. Just skip it and all
strings are going to be output on the same line. However, you should
terminate the line yourself sending the endl or "\n" to the stream after
the
last thing you want to output. In principle it works just like the normal
cout stream.

Cheers
Chris

Jul 23 '05 #3

P: n/a
GB
winbatch wrote:
I've create a 'Log' class, who creates and writes to log files. I was
able
to overload the << operator so that I could write to my log as follows:

Log logOne("log.txt", true, "\n" );
logOne<<"BLAH"<<"BLAH2";

In the constructor, the 'true' refers to having the log class write out
a
datetime stamp of each log entry, while the '\n' indicates how to
terminate
the log line.

The problem is that when I use the syntax about (<<"A"<<"B" ), etc, it
ends
up writing multiple lines because the << function is getting called
each
time. What I would like to do is have A and B be concatenated into one
string and then do the actual call to write the log line once. How do I
know
if I am the 'LAST' item being sent to the << so that I can store the
intermediate values and not write it out unless I am last?


Instead of writing the timestamp from within the insertion function,
require that it be added explicitly. You can do this by defining your
own timestamp stream manipulator, logstamp, which you would then use
like this:

log << logstamp << "blah1" << "blah2" << std::endl;
I have done something similar to this. Another thing I have done to make
the log thread-safe is to take advantage of the C++ property that
temporary objects are guaranteed not to be destroyed until the entire
expression in which it appears is evaluated. I take advantage of this by
acquiring a log mutex in logstamp's constructor and releasing it in its
destructor. That way the entire string of insertions is guaranteed to be
atomic. No need for printf-style output mechanism. Details are
off-topic, though.

Gregg
Jul 23 '05 #4

P: n/a

"Dan Hoffman" <da********@nyc.rr.com> wrote in message
news:w0***************@twister.nyc.rr.com...
Chris,

I don't have an endl in my writeLog function. The reason is that the
constructor takes a parameter which will be the EOL for the log. The reason for this is that I have another class which contains multiple logs and I
just send it a string and it will call the writeLog of each of the Log
objects inside. Since certain logs will have different terminators, I
didn't want to have to deal with this when I passed the string to be logged, but rather it be part of the Log object itself.

I realize that the << is being called twice, and that's exactly the problem. I only want the log to be written to the file when I'm on the LAST call to
the <<. All previous calls should simply append the string to some buffer
so that when I hit the last call to <<, I can write out my buffer (with the last string included).

This is the writeLog function for your reference. Regarding your advice
about const, I have taken your advice.

void Log::writeLog( const string &logLine )
{
content=logLine;
if ( !out->is_open() )
throw DHException( 3, "Attempt to write to log file [", fileName.c_str(),
"] without opening first!");

if ( includeDate )
{
current.now();
content = Date::getFormattedDate( current ) +">" + content + suffix;
}
out->write( content.c_str(), content.size() );
out->flush();

if ( !out->is_open() )
throw DHException ( 3, "Could not write to log file [", fileName.c_str(), "] !");

}

"Chris Theis" <Ch*********@nospam.cern.ch> wrote in message
news:cu**********@sunnews.cern.ch...

"winbatch" <ho********@gmail.com> wrote in message
news:11*********************@o13g2000cwo.googlegro ups.com...
Hi,
I'm trying to play with classes and I'm having trouble with a
theoretical
problem.

I've create a 'Log' class, who creates and writes to log files. I was
able
to overload the << operator so that I could write to my log as follows:

Log logOne("log.txt", true, "\n" );
logOne<<"BLAH"<<"BLAH2";

In the constructor, the 'true' refers to having the log class write out
a
datetime stamp of each log entry, while the '\n' indicates how to
terminate
the log line.

The problem is that when I use the syntax about (<<"A"<<"B" ), etc, it
ends
up writing multiple lines because the << function is getting called
each
time.


Operator << must (!) be called here twice because you call it twice ;-) So that behavior absolutely makes sense.
What I would like to do is have A and B be concatenated into one
string and then do the actual call to write the log line once. How do I
know
if I am the 'LAST' item being sent to the << so that I can store the
intermediate values and not write it out unless I am last?

Here is my function: (quite simple)
Log & operator << (string a)
{
writeLog(a);
return *this;
}


Hi Dan,

I personally would find it clearer to implement the date/time stamp as a
manipulator as already recommended in another posting. Otherwise you could
implement your log to buffer the strings until your own user supplied endl -
manipulator signals a flush.

Cheers
Chris
Jul 23 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.