943,969 Members | Top Members by Rank

Ad:
  • C Discussion Thread
  • Unsolved
  • Views: 6769
  • C RSS
You are currently viewing page 1 of this multi-page discussion thread
May 5th, 2005
0

overloading Operator << to accept endl

Expand Post »
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 >>
Reputation Points: 68
Solved Threads: 18
Posting Pro in Training
winbatch is offline Offline
466 posts
since Feb 2005
May 5th, 2005
0

Re: overloading Operator << to accept endl

(Sorry, posted something I thought was working but was not...question still stands!)
Reputation Points: 68
Solved Threads: 18
Posting Pro in Training
winbatch is offline Offline
466 posts
since Feb 2005
May 5th, 2005
0

Re: overloading Operator << to accept endl

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.
Administrator
Reputation Points: 6442
Solved Threads: 1393
Bad Cop
Narue is offline Offline
11,807 posts
since Sep 2004
May 5th, 2005
0

Re: overloading Operator << to accept endl

How do I get from an ostream to a string or an ostringstream? (That's what my writeLog function expects..)
Reputation Points: 68
Solved Threads: 18
Posting Pro in Training
winbatch is offline Offline
466 posts
since Feb 2005
May 5th, 2005
0

Re: overloading Operator << to accept endl

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 >>
Reputation Points: 68
Solved Threads: 18
Posting Pro in Training
winbatch is offline Offline
466 posts
since Feb 2005
May 5th, 2005
0

Re: overloading Operator << to accept endl

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. }
Administrator
Reputation Points: 6442
Solved Threads: 1393
Bad Cop
Narue is offline Offline
11,807 posts
since Sep 2004
May 5th, 2005
0

Re: overloading Operator << to accept endl

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 >>
Reputation Points: 68
Solved Threads: 18
Posting Pro in Training
winbatch is offline Offline
466 posts
since Feb 2005
May 5th, 2005
0

Re: overloading Operator << to accept endl

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.
Administrator
Reputation Points: 6442
Solved Threads: 1393
Bad Cop
Narue is offline Offline
11,807 posts
since Sep 2004
May 6th, 2005
0

Re: overloading Operator << to accept endl

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?
Reputation Points: 68
Solved Threads: 18
Posting Pro in Training
winbatch is offline Offline
466 posts
since Feb 2005
May 6th, 2005
0

Re: overloading Operator << to accept endl

>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. }
Administrator
Reputation Points: 6442
Solved Threads: 1393
Bad Cop
Narue is offline Offline
11,807 posts
since Sep 2004

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in C Forum Timeline: Read unlimited no. of people.
Next Thread in C Forum Timeline: Please help





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC