| | |
overloading Operator << to accept endl
![]() |
I'm trying to overload my 'Log' class so that I can pass 'endl' to it. Given the obscure nature of the compiler errors for template classes, I'm not sure what to put on the 'right hand side'.
For example, these work fine. ..
How do I do one that accepts endl?
This is the compiler's complaint:
<< moderator edit: added [code][/code] tags >>
For example, these work fine. ..
C Syntax (Toggle Plain Text)
Log & operator << (ostringstream & a) { writeLog(a.str()); return *this; } Log & operator << (const string & a) { writeLog(a); return *this; }
How do I do one that accepts endl?
This is the compiler's complaint:
C Syntax (Toggle Plain Text)
line 62: Error: The operation "Log << std::basic_ostream<std::charT, std::traits>&(*)(std::basic_ostream<std::charT, std::traits>&)" is illegal.
For somewhat obscure reasons, operator<< should be a non-member function:
If Log doesn't have a public interface that allows everyone to write the log somewhere, you'll need to make the function a friend of Log as well. Without seeing your Log class declaration, it's hard to tell exactly what you need, but if you define operator<< in the conventional way (as above), your endl problem just goes away.
C Syntax (Toggle Plain Text)
ostream& operator<< ( ostream& out, const Log& log ) { log.writeLog ( out ); return out; }
I'm here to prove you wrong.
Here's Log.h:
----------------------------
Here's attempted uisage:
----------------
<< moderator edit: added [code][/code] tags >>
----------------------------
C Syntax (Toggle Plain Text)
#include "MainInclude.h" #ifndef __LOG_CLASS__ #define __LOG_CLASS__ #define MAX_LOG_SIZE 5000 using namespace std; class Log { private: Date current; string fileName; ofstream *out; bool screenOutput; bool includeDate; string contentSeparator; bool isOpenFlag; public: Log(); Log( const string & file, bool withDate=false ); ~Log(); bool isOpen () { return isOpenFlag; } string getFileName() { return fileName; } void setContentSeparator( const string & sep ); void open(); void close(); void writeLog ( const double & logLine ); void writeLog ( const string & logLine ); void writeLog ( const ostringstream & inputStream); void writeLog( const char * logLine, ... ); void writeLog ( Printable &a ); void setIncludeDate( bool doDate ) { includeDate = doDate; } void setFileName( string theFile) { fileName = theFile; screenOutput=false; } /* THE NEW FUNCTION FOR ENDL */ Log & operator << (ostream & a) { ostringstream o; o<<a; writeLog(o); return *this; } Log & operator << (ostringstream & a) { writeLog(a.str()); return *this; } Log & operator << (const string & a) { writeLog(a); return *this; } Log & operator << ( const char * a) { writeLog(a); return *this; } Log & operator << ( const double & a) { writeLog(a); return *this; } /* To handle any class that extends Printable... function must support toString() */ Log & operator << ( Printable &a ) { writeLog( a.toString() ); return *this; } }; #endif
Here's attempted uisage:
C Syntax (Toggle Plain Text)
Log * screenLog; screenLog = new Log(); *screenLog<<"Done loading session, successful..."<<endl;
----------------
C Syntax (Toggle Plain Text)
Error: The operation "Log << std::basic_ostream<std::charT, std::traits>&(*)(std::basic_ostream<std::charT, std::traits>&)" is illegal.
Can you show me the definitions of writeLog? Because it seems to me you're going about this in a funky way.
Edit: Unless, of course, you're trying to wrap and simulate a stream, where something like this is appropriate:
Edit: Unless, of course, you're trying to wrap and simulate a stream, where something like this is appropriate:
C Syntax (Toggle Plain Text)
#include <iostream> #include <string> using namespace std; class Header { string _date; string _name; public: Header(const string& date, const string& name) : _date(date), _name(name) {} friend ostream& operator<<(ostream& out, const Header& h ) { return out<< h._date <<" -- "<< h._name <<'\n'; } }; class Log { ostream& _out; Header _header; bool _first; public: Log(const Header& header, ostream& out = cout) : _header(header), _out(out), _first(true) {}; ostream& operator<<(const string& s) { if (_first) { _out<< _header <<'\n'; _first = false; } return _out<< s; } }; int main() { Log log(Header("05-05-2005", "Narue's Log")); log<<"This is a test"<<endl; log<<"Another test"<<endl; log<<"Last test"<<endl; }
I'm here to prove you wrong.
This is Log.cpp.
-----------------
<< moderator edit: added [code][/code] tags >>
-----------------
C Syntax (Toggle Plain Text)
#include "Log.h" void Log::setContentSeparator( const string & sep ) { contentSeparator = sep; } Log::Log() { screenOutput=true; isOpenFlag = false; out=NULL; fileName="CONSOLE"; setContentSeparator ( ">"); includeDate=false; } Log::Log( const string & file, bool withDate) { screenOutput=false; isOpenFlag = false; out=NULL; fileName = file; includeDate = withDate; setContentSeparator ( ">"); } void Log::open() { if ( screenOutput ) { isOpenFlag = true; return; } if ( out != NULL ) throw DHException( "File [" + fileName + "] is already open!"); out = new ofstream(fileName.c_str(), ofstream::out); if ( !out->is_open() ) { throw DHException( "Could not open file [" + fileName + "]!"); } isOpenFlag = true; } void Log::writeLog( Printable &a ) { writeLog( a.toString() ); } void Log::writeLog ( const ostringstream & inputStream) { writeLog( inputStream.str()); } void Log::writeLog( const double & logLine ) { ostringstream o; o<<logLine; writeLog( o.str() ); } void Log::writeLog( const string & logLine ) { if ( !screenOutput ) { if ( fileName=="" ) throw DHException( "Log filename has not been set!"); if ( out == NULL || !out->is_open() ) throw DHException( "Could not write to log file [" + fileName + "]. File was never opened or was previously closed!"); } if ( includeDate ) { current.now(); if ( !screenOutput ) *out<<Date::getFormattedDate( current )<<contentSeparator<<logLine; else { cout<<Date::getFormattedDate( current )<<contentSeparator<<logLine; cout<<flush; } } else { if ( !screenOutput ) *out<<logLine; else { cout<<logLine; cout<<flush; } } if ( !screenOutput ) { out->flush(); if ( !out->is_open() ) throw DHException ( "Could not write to log file [" + fileName + "] !"); } } void Log::writeLog(const char * logLine, ... ) { va_list args; va_start (args, logLine); char *dan = new char[MAX_LOG_SIZE]; long count = vsnprintf (dan, MAX_LOG_SIZE, logLine, args); va_end (args); string temp; if ( count == -1 || count > MAX_LOG_SIZE ) { temp=dan; temp+="...<LOG TRUNCATED>..."; } else temp=dan; if ( dan !=NULL ) { delete dan; } writeLog( temp ); } void Log::close() { if ( !screenOutput ) { if ( out !=NULL ) { if ( out->is_open() ) out->close(); out=NULL; } } } Log::~Log() { if ( out != NULL ) { if ( out->is_open() ) out->close(); delete out; } }
Okay, so what you want really is like my example. In that case, notice how every time I define operator<<, it returns an ostream reference. I do this so that chaining is possible:
When you return an ostream reference, endl should work fine.
C Syntax (Toggle Plain Text)
log<< something << somethingelse <<endl;
I'm here to prove you wrong.
Narue,
I'm having trouble understanding how this works. I took your sample, made some changes to remove some stuff (like the date, etc.) and it works nicely. My question is this. Is there a way to populate the _out not as part of the constructor? Also, is there an equivalent way of doing this to an ofstream? The reason I ask is that my Log class either writes to a file or to the console, and I would like to choose where it goes inside the body of the constructor... Also, is the only way to do this to create that Header class? There's no way to do it simply inside the Log class?
I'm having trouble understanding how this works. I took your sample, made some changes to remove some stuff (like the date, etc.) and it works nicely. My question is this. Is there a way to populate the _out not as part of the constructor? Also, is there an equivalent way of doing this to an ofstream? The reason I ask is that my Log class either writes to a file or to the console, and I would like to choose where it goes inside the body of the constructor... Also, is the only way to do this to create that Header class? There's no way to do it simply inside the Log class?
>and I would like to choose where it goes inside the body of the constructor...
You can. As defined, Log defaults to cout, and you can override that by passing a second argument. Say, a file stream:
>Also, is the only way to do this to create that Header class?
The header class is completely different. It's there merely as a convenience so that when you open a log, you know when it was created and it has a descriptive name. You can easily do without it:
You can. As defined, Log defaults to cout, and you can override that by passing a second argument. Say, a file stream:
C Syntax (Toggle Plain Text)
ofstream out("somefile"); Log log(header, out); // Assuming a suitably defined header
The header class is completely different. It's there merely as a convenience so that when you open a log, you know when it was created and it has a descriptive name. You can easily do without it:
C Syntax (Toggle Plain Text)
#include <iostream> #include <string> using namespace std; class Log { ostream& _out; bool _first; public: Log(ostream& out = cout) : _out(out), _first(true) {}; ostream& operator<<(const string& s) { return _out<< s; } }; int main() { Log log; log<<"This is a test"<<endl; log<<"Another test"<<endl; log<<"Last test"<<endl; }
I'm here to prove you wrong.
![]() |
Other Threads in the C Forum
- Previous Thread: Read unlimited no. of people.
- Next Thread: Please help
| Thread Tools | Search this Thread |
* adobe ansi api array asterisks binarysearch calculate centimeter changingto char character cm convert copyimagefile cprogramme creafecopyofanytypeoffileinc createcopyoffile csyntax database directory feet fflush fgets file fork forloop frequency function givemetehcodez grade graphics gtkgcurlcompiling gtkwinlinux hacking highest histogram i/o inches infiniteloop input intmain() iso kernel keyboard km linked linkedlist linux linuxsegmentationfault list locate looping loopinsideloop. lowest match microsoft mqqueue mysql number oddnumber odf open opendocumentformat owf pattern pdf performance posix probleminc process program programming radix recv recvblocked repetition research reversing scanf scheduling segmentationfault send sequential socket socketprograming stack standard string systemcall threads turboc unix user variable voidmain() wab whythiscodecausesegmentationfault windows.h windowsapi






