From: Andrew Falanga on
Hi everybody,

I asked a question yesterday that is related to this one. Below is,
basically, what I have in a set of files for a logging class for my
programs. Now, I wanted to overload the << operator to be used much
like is done with std::cout, etc.

Below is code, that won't compile, but that shows what I've done.
Basically, when calling my overloaded << function, I need to have
certain things done if the argument is either of type logModes or
logDirectives. If not, use the template to generate code for it.

//Log.h
enum logModes { stdoutonly, logfileonly, clear };
enum logDirectives { flush };

#define FLUSH_LOG flush;

class Log {
std::string logFileName;
std::fstream logFile;

logModes currMode;

public:
// c-tors and d-tors here

template <typename T>
Log& operator << ( T t ) {
std::ostringstream os;
os = t;
logFile << os.str();
return *this;
}

Log& operator << ( logModes );
Log& operator << ( logDirectives );

};

Now, the definitions for the two overloaded versions of the "<<"
function are in Log.cpp. I was beginning to think, however, that
although all modules compiled and linked, when I ran my programs the
over loaded functions don't get called because the log files were
getting zeros instead of new lines for lines like:

# include <Log.h>
Log myProgLog;

myProgLog << "This is a log line" << FLUSH_LOG;

Which ended up being, "This is a log line0" in my log files. This
lead me to believe that the compiler wasn't selecting which function
to use correctly.

Andy
From: Ron Natalie on
You're going about it the wrong way. You'll never
get operator<< to work property the way you are trying
to do it because class operator<< overloads expect to
deal with ostreams.

What you want to do is define a stream buffer that
outputs to your log file and init an ostream from
it.

Here's a little hack version of one

// Not the most efficient implementation
class LogStreamBuf : public std::basic_streambuf<char,
std::char_traits<char> > {
virtual int_type overflow(int_type ic) {
if(ic != EOF) {
char c = ic;
LogPut(&c, 1);
}
return ic;
}
virtual std::streamsize xsputn(const char* s, std::streamsize num) {
LogPut(s, num);
return num;
}
}

Replace LogPut in xsputn with one that writes to your log file.

std::ostream LogOut(&logbuf);

LogOut << "this will work with anything that has an ostream<< overload\n";
From: Andrew Falanga on
On Jan 17, 6:09 am, Ron Natalie <r...(a)spamcop.net> wrote:
> You're going about it the wrong way. You'll never
> get operator<< to work property the way you are trying
> to do it because class operator<< overloads expect to
> deal with ostreams.
>
> What you want to do is define a stream buffer that
> outputs to your log file and init an ostream from
> it.
>
> Here's a little hack version of one
>
> // Not the most efficient implementation
> class LogStreamBuf : public std::basic_streambuf<char,
> std::char_traits<char> > {
> virtual int_type overflow(int_type ic) {
> if(ic != EOF) {
> char c = ic;
> LogPut(&c, 1);
> }
> return ic;
> }
> virtual std::streamsize xsputn(const char* s, std::streamsize num) {
> LogPut(s, num);
> return num;
> }
>
> }
>
> Replace LogPut in xsputn with one that writes to your log file.
>
> std::ostream LogOut(&logbuf);
>
> LogOut << "this will work with anything that has an ostream<< overload\n";

Ron,

I must admit to not fully understanding what it is you're doing. Can
you walk though it step by step?

Andy