Connecting Tech Pros Worldwide Help | Site Map

Help with operator overloading of <<

  #1  
Old July 23rd, 2005, 01:50 AM
winbatch
Guest
 
Posts: 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...

  #2  
Old July 23rd, 2005, 01:50 AM
Chris Theis
Guest
 
Posts: n/a

re: Help with operator overloading of <<



"winbatch" <hoffmandan@gmail.com> wrote in message
news:1108304740.306943.65180@o13g2000cwo.googlegro ups.com...[color=blue]
> 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.[/color]

Operator << must (!) be called here twice because you call it twice ;-) So
that behavior absolutely makes sense.
[color=blue]
> 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;
> }
>[/color]

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


  #3  
Old July 23rd, 2005, 01:51 AM
Dan Hoffman
Guest
 
Posts: n/a

re: Help with operator overloading of <<


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" <Chris.Theis@nospam.cern.ch> wrote in message
news:cunsja$iki$1@sunnews.cern.ch...[color=blue]
>
> "winbatch" <hoffmandan@gmail.com> wrote in message
> news:1108304740.306943.65180@o13g2000cwo.googlegro ups.com...[color=green]
>> 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.[/color]
>
> Operator << must (!) be called here twice because you call it twice ;-) So
> that behavior absolutely makes sense.
>[color=green]
>> 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;
>> }
>>[/color]
>
> 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
>
>[/color]


  #4  
Old July 23rd, 2005, 01:51 AM
GB
Guest
 
Posts: n/a

re: Help with operator overloading of <<


winbatch wrote:[color=blue]
> 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?[/color]

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
  #5  
Old July 23rd, 2005, 01:52 AM
Chris Theis
Guest
 
Posts: n/a

re: Help with operator overloading of <<



"Dan Hoffman" <danhoffman@nyc.rr.com> wrote in message
news:w0PPd.6442$534.73@twister.nyc.rr.com...[color=blue]
> 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[/color]
reason[color=blue]
> 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[/color]
logged,[color=blue]
> but rather it be part of the Log object itself.
>
> I realize that the << is being called twice, and that's exactly the[/color]
problem.[color=blue]
> 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[/color]
the[color=blue]
> 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 [",[/color]
fileName.c_str(),[color=blue]
> "] !");
>
> }
>
> "Chris Theis" <Chris.Theis@nospam.cern.ch> wrote in message
> news:cunsja$iki$1@sunnews.cern.ch...[color=green]
> >
> > "winbatch" <hoffmandan@gmail.com> wrote in message
> > news:1108304740.306943.65180@o13g2000cwo.googlegro ups.com...[color=darkred]
> >> 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.[/color]
> >
> > Operator << must (!) be called here twice because you call it twice ;-)[/color][/color]
So[color=blue][color=green]
> > that behavior absolutely makes sense.
> >[color=darkred]
> >> 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;
> >> }
> >>[/color]
> >[/color][/color]

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


Closed Thread


Similar Threads
Thread Thread Starter Forum Replies Last Post
question regarding operator << overloading Goran answers 8 June 27th, 2008 05:44 PM
Help appreciated with identifying a little bug(intro std, map<> and overloading related) brzozo2@uwindsor.ca answers 2 October 11th, 2006 11:55 PM
problem regarding overloading of operator <<. Ashwin answers 17 July 28th, 2006 10:55 AM
Overloading operator<< to output private class-data Andreas answers 6 March 5th, 2006 01:15 AM