overloading Operator << to accept endl

Reply

Join Date: Feb 2005
Posts: 466
Reputation: winbatch is on a distinguished road 
Solved Threads: 18
winbatch's Avatar
winbatch winbatch is offline Offline
Posting Pro in Training

overloading Operator << to accept endl

 
0
  #1
May 5th, 2005
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. ..
  1. Log & operator << (ostringstream & a)
  2. {
  3. writeLog(a.str());
  4. return *this;
  5. }
  6.  
  7.  
  8. Log & operator << (const string & a)
  9. {
  10. writeLog(a);
  11. return *this;
  12. }

How do I do one that accepts endl?

This is the compiler's complaint:
  1. line 62: Error: The operation "Log << std::basic_ostream<std::charT, std::traits>&(*)(std::basic_ostream<std::charT, std::traits>&)" is illegal.
<< moderator edit: added [code][/code] tags >>
Reply With Quote Quick reply to this message  
Join Date: Feb 2005
Posts: 466
Reputation: winbatch is on a distinguished road 
Solved Threads: 18
winbatch's Avatar
winbatch winbatch is offline Offline
Posting Pro in Training

Re: overloading Operator << to accept endl

 
0
  #2
May 5th, 2005
(Sorry, posted something I thought was working but was not...question still stands!)
Reply With Quote Quick reply to this message  
Join Date: Sep 2004
Posts: 7,567
Reputation: Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute 
Solved Threads: 707
Team Colleague
Narue's Avatar
Narue Narue is offline Offline
Code Goddess

Re: overloading Operator << to accept endl

 
0
  #3
May 5th, 2005
For somewhat obscure reasons, operator<< should be a non-member function:
  1. ostream& operator<< ( ostream& out, const Log& log )
  2. {
  3. log.writeLog ( out );
  4. return out;
  5. }
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.
I'm here to prove you wrong.
Reply With Quote Quick reply to this message  
Join Date: Feb 2005
Posts: 466
Reputation: winbatch is on a distinguished road 
Solved Threads: 18
winbatch's Avatar
winbatch winbatch is offline Offline
Posting Pro in Training

Re: overloading Operator << to accept endl

 
0
  #4
May 5th, 2005
How do I get from an ostream to a string or an ostringstream? (That's what my writeLog function expects..)
Reply With Quote Quick reply to this message  
Join Date: Feb 2005
Posts: 466
Reputation: winbatch is on a distinguished road 
Solved Threads: 18
winbatch's Avatar
winbatch winbatch is offline Offline
Posting Pro in Training

Re: overloading Operator << to accept endl

 
0
  #5
May 5th, 2005
Here's Log.h:
----------------------------
  1. #include "MainInclude.h"
  2.  
  3. #ifndef __LOG_CLASS__
  4. #define __LOG_CLASS__
  5.  
  6.  
  7. #define MAX_LOG_SIZE 5000
  8.  
  9. using namespace std;
  10.  
  11. class Log
  12. {
  13. private:
  14. Date current;
  15. string fileName;
  16. ofstream *out;
  17. bool screenOutput;
  18.  
  19. bool includeDate;
  20. string contentSeparator;
  21.  
  22. bool isOpenFlag;
  23.  
  24.  
  25.  
  26.  
  27.  
  28. public:
  29.  
  30. Log();
  31. Log( const string & file, bool withDate=false );
  32. ~Log();
  33.  
  34.  
  35. bool isOpen () { return isOpenFlag; }
  36.  
  37.  
  38. string getFileName() { return fileName; }
  39. void setContentSeparator( const string & sep );
  40.  
  41.  
  42. void open();
  43. void close();
  44.  
  45.  
  46.  
  47. void writeLog ( const double & logLine );
  48. void writeLog ( const string & logLine );
  49. void writeLog ( const ostringstream & inputStream);
  50. void writeLog( const char * logLine, ... );
  51. void writeLog ( Printable &a );
  52.  
  53.  
  54.  
  55.  
  56.  
  57. void setIncludeDate( bool doDate ) { includeDate = doDate; }
  58. void setFileName( string theFile)
  59. {
  60. fileName = theFile;
  61. screenOutput=false;
  62. }
  63.  
  64. /* THE NEW FUNCTION FOR ENDL */
  65. Log & operator << (ostream & a)
  66. {
  67. ostringstream o;
  68. o<<a;
  69. writeLog(o);
  70. return *this;
  71. }
  72.  
  73. Log & operator << (ostringstream & a)
  74. {
  75. writeLog(a.str());
  76. return *this;
  77. }
  78.  
  79.  
  80. Log & operator << (const string & a)
  81. {
  82. writeLog(a);
  83. return *this;
  84. }
  85.  
  86. Log & operator << ( const char * a)
  87. {
  88. writeLog(a);
  89. return *this;
  90.  
  91. }
  92.  
  93.  
  94. Log & operator << ( const double & a)
  95. {
  96. writeLog(a);
  97. return *this;
  98. }
  99.  
  100. /* To handle any class that extends Printable... function must support toString() */
  101. Log & operator << ( Printable &a )
  102. {
  103.  
  104. writeLog( a.toString() );
  105. return *this;
  106. }
  107. };
  108. #endif


Here's attempted uisage:
  1. Log * screenLog;
  2. screenLog = new Log();
  3. *screenLog<<"Done loading session, successful..."<<endl;

----------------
  1. Error: The operation "Log << std::basic_ostream<std::charT, std::traits>&(*)(std::basic_ostream<std::charT, std::traits>&)" is illegal.
<< moderator edit: added [code][/code] tags >>
Reply With Quote Quick reply to this message  
Join Date: Sep 2004
Posts: 7,567
Reputation: Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute 
Solved Threads: 707
Team Colleague
Narue's Avatar
Narue Narue is offline Offline
Code Goddess

Re: overloading Operator << to accept endl

 
0
  #6
May 5th, 2005
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:
  1. #include <iostream>
  2. #include <string>
  3.  
  4. using namespace std;
  5.  
  6. class Header {
  7. string _date;
  8. string _name;
  9. public:
  10. Header(const string& date, const string& name)
  11. : _date(date), _name(name) {}
  12. friend ostream& operator<<(ostream& out, const Header& h )
  13. {
  14. return out<< h._date <<" -- "<< h._name <<'\n';
  15. }
  16. };
  17.  
  18. class Log {
  19. ostream& _out;
  20. Header _header;
  21. bool _first;
  22. public:
  23. Log(const Header& header, ostream& out = cout)
  24. : _header(header), _out(out), _first(true) {};
  25. ostream& operator<<(const string& s)
  26. {
  27. if (_first) {
  28. _out<< _header <<'\n';
  29. _first = false;
  30. }
  31. return _out<< s;
  32. }
  33. };
  34.  
  35. int main()
  36. {
  37. Log log(Header("05-05-2005", "Narue's Log"));
  38.  
  39. log<<"This is a test"<<endl;
  40. log<<"Another test"<<endl;
  41. log<<"Last test"<<endl;
  42. }
I'm here to prove you wrong.
Reply With Quote Quick reply to this message  
Join Date: Feb 2005
Posts: 466
Reputation: winbatch is on a distinguished road 
Solved Threads: 18
winbatch's Avatar
winbatch winbatch is offline Offline
Posting Pro in Training

Re: overloading Operator << to accept endl

 
0
  #7
May 5th, 2005
This is Log.cpp.
-----------------
  1. #include "Log.h"
  2.  
  3.  
  4.  
  5. void Log::setContentSeparator( const string & sep )
  6. {
  7. contentSeparator = sep;
  8. }
  9.  
  10. Log::Log()
  11. {
  12. screenOutput=true;
  13. isOpenFlag = false;
  14. out=NULL;
  15. fileName="CONSOLE";
  16. setContentSeparator ( ">");
  17. includeDate=false;
  18. }
  19.  
  20. Log::Log( const string & file, bool withDate)
  21. {
  22. screenOutput=false;
  23. isOpenFlag = false;
  24. out=NULL;
  25. fileName = file;
  26. includeDate = withDate;
  27. setContentSeparator ( ">");
  28.  
  29. }
  30. void Log::open()
  31. {
  32.  
  33. if ( screenOutput )
  34. {
  35. isOpenFlag = true;
  36. return;
  37. }
  38. if ( out != NULL )
  39. throw DHException( "File [" + fileName + "] is already open!");
  40.  
  41. out = new ofstream(fileName.c_str(), ofstream::out);
  42.  
  43.  
  44. if ( !out->is_open() )
  45. {
  46.  
  47. throw DHException( "Could not open file [" + fileName + "]!");
  48. }
  49.  
  50. isOpenFlag = true;
  51.  
  52. }
  53.  
  54. void Log::writeLog( Printable &a )
  55. {
  56. writeLog( a.toString() );
  57. }
  58. void Log::writeLog ( const ostringstream & inputStream)
  59. {
  60. writeLog( inputStream.str());
  61. }
  62.  
  63. void Log::writeLog( const double & logLine )
  64. {
  65. ostringstream o;
  66. o<<logLine;
  67. writeLog( o.str() );
  68. }
  69.  
  70. void Log::writeLog( const string & logLine )
  71. {
  72.  
  73. if ( !screenOutput )
  74. {
  75. if ( fileName=="" )
  76. throw DHException( "Log filename has not been set!");
  77.  
  78. if ( out == NULL || !out->is_open() )
  79. throw DHException( "Could not write to log file [" + fileName + "]. File was never opened or was previously closed!");
  80.  
  81. }
  82. if ( includeDate )
  83. {
  84. current.now();
  85. if ( !screenOutput )
  86. *out<<Date::getFormattedDate( current )<<contentSeparator<<logLine;
  87. else
  88. {
  89. cout<<Date::getFormattedDate( current )<<contentSeparator<<logLine;
  90. cout<<flush;
  91. }
  92.  
  93. }
  94. else
  95. {
  96. if ( !screenOutput )
  97. *out<<logLine;
  98. else
  99. {
  100. cout<<logLine;
  101. cout<<flush;
  102. }
  103. }
  104.  
  105. if ( !screenOutput )
  106. {
  107. out->flush();
  108.  
  109. if ( !out->is_open() )
  110. throw DHException ( "Could not write to log file [" + fileName + "] !");
  111.  
  112. }
  113. }
  114.  
  115.  
  116. void Log::writeLog(const char * logLine, ... )
  117. {
  118.  
  119. va_list args;
  120. va_start (args, logLine);
  121. char *dan = new char[MAX_LOG_SIZE];
  122. long count = vsnprintf (dan, MAX_LOG_SIZE, logLine, args);
  123. va_end (args);
  124.  
  125. string temp;
  126.  
  127.  
  128. if ( count == -1 || count > MAX_LOG_SIZE )
  129. {
  130. temp=dan;
  131. temp+="...<LOG TRUNCATED>...";
  132. }
  133. else
  134. temp=dan;
  135.  
  136. if ( dan !=NULL )
  137. {
  138. delete dan;
  139. }
  140. writeLog( temp );
  141.  
  142. }
  143.  
  144. void Log::close()
  145. {
  146. if ( !screenOutput )
  147. {
  148. if ( out !=NULL )
  149. {
  150. if ( out->is_open() )
  151. out->close();
  152. out=NULL;
  153. }
  154. }
  155. }
  156. Log::~Log()
  157. {
  158.  
  159. if ( out != NULL )
  160. {
  161. if ( out->is_open() )
  162. out->close();
  163.  
  164. delete out;
  165. }
  166. }
<< moderator edit: added [code][/code] tags >>
Reply With Quote Quick reply to this message  
Join Date: Sep 2004
Posts: 7,567
Reputation: Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute 
Solved Threads: 707
Team Colleague
Narue's Avatar
Narue Narue is offline Offline
Code Goddess

Re: overloading Operator << to accept endl

 
0
  #8
May 5th, 2005
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:
  1. log<< something << somethingelse <<endl;
When you return an ostream reference, endl should work fine.
I'm here to prove you wrong.
Reply With Quote Quick reply to this message  
Join Date: Feb 2005
Posts: 466
Reputation: winbatch is on a distinguished road 
Solved Threads: 18
winbatch's Avatar
winbatch winbatch is offline Offline
Posting Pro in Training

Re: overloading Operator << to accept endl

 
0
  #9
May 6th, 2005
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?
Reply With Quote Quick reply to this message  
Join Date: Sep 2004
Posts: 7,567
Reputation: Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute 
Solved Threads: 707
Team Colleague
Narue's Avatar
Narue Narue is offline Offline
Code Goddess

Re: overloading Operator << to accept endl

 
0
  #10
May 6th, 2005
>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:
  1. ofstream out("somefile");
  2. Log log(header, out); // Assuming a suitably defined header
>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:
  1. #include <iostream>
  2. #include <string>
  3.  
  4. using namespace std;
  5.  
  6. class Log {
  7. ostream& _out;
  8. bool _first;
  9. public:
  10. Log(ostream& out = cout)
  11. : _out(out), _first(true) {};
  12. ostream& operator<<(const string& s)
  13. {
  14. return _out<< s;
  15. }
  16. };
  17.  
  18. int main()
  19. {
  20. Log log;
  21.  
  22. log<<"This is a test"<<endl;
  23. log<<"Another test"<<endl;
  24. log<<"Last test"<<endl;
  25. }
I'm here to prove you wrong.
Reply With Quote Quick reply to this message  
Reply

This thread is more than three months old.
Perhaps start a new thread instead?
Message:



Other Threads in the C Forum
Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC