Archived

This topic is now archived and is closed to further replies.

IFooBar

overloading the insertion operator to take in 'endl'

Recommended Posts

here''s the situation. I have a logger class that has a templated insertion operator overload. The logger logs stuff in html. So i need to make a specialization to take in endl and instead of passing in ''\n'' I have to pass in "
" (for html end line). I want to be able to do this logger<< "blah"<< std::endl; here''s a little code to show how the logger class is structured
class logger
{
   std::ofstream mFile;

public:

   template<class T0> logger& operator << ( T0 val )
   {
      mFile<< val;
   }
};
Now I tried making a template specialization that takes in a function pointer that''s in the form of a manipulator
typedef std::basic_ostream<TCHAR, std::char_traits<TCHAR> >& (*_manip)(std::basic_ostream<TCHAR, std::char_traits<TCHAR> >&);
but still dont work. Any help would be greatly appreciated

Share this post


Link to post
Share on other sites
i also have a html logger, but it works a bit diffrent.

i have a base object:

class AInfoString
{
public:
friend std::ostream& operator<< (std::ostream&, axpAInfoString&);
virtual void Log() = 0;
virtual std::string InfoString() = 0;
};

// note the namespace!!!

std::ostream& axp::operator<< (std::ostream& lStream, AInfoString& lRight)
{
lStream << lRight.InfoString();
}


as u can see, log and infostring are pure virtual, and any object that derives from ainfostring must implement them, and when they do, i can use it''s << operator, which calls infostring(). so anything u want to log, just build a string in infostring and that''s it...

cout << CAnyObjectWhichDerivedFromAInfoString;

simple...

Share this post


Link to post
Share on other sites
Overload operator << again only have it take a pointer to a function with a return type std::ostream& and that takes a reference or pointer to an ostream as a parameter. Then call that function passing your mFile as a parameter. std::endl is a function. Also, return *this in that function as well as the one you already defined.

IE

class logger
{
std::ofstream mFile;
public:
template<class T0>
logger& operator << ( T0 val )
{
mFile<< val;
return *this;
}
logger& operator << ( std::ostream& (&Modifier)( std::ostream& ) )
{
Modifier( mFile );
return *this;
}
};


EDIT: Fixed/Typos

[edited by - Polymorphic OOP on September 2, 2003 2:50:28 PM]

Share this post


Link to post
Share on other sites
polymorphic: Your function parameter is exactly the same as my typedef except that I was using a TCHAR instead of a char. It also dosnt work. The compiler gives an error:

error C2678: binary ''<<'' : no operator found which takes a left-hand operand of type ''Rex::Logger'' (or there is no acceptable conversion)


endl is a templated funtion. So wont I need something like a friend specialization in my logger class? something like:

class logger
{
...
template<> friend std::ostream& endl( logger& l )
{
return l.mFile;
}
...
};


although the above dosnt work either

Share this post


Link to post
Share on other sites
I think you''re suppose to watch for the ''\n'' character in your stream-buffer, and then you need to override the flush method of the stream class.

In theory what you need to do is write a new stream buffer, not a new stream class.


Streams aren''t exactly my strong point (nor anyone I know for that matter), so I could be off.

(Just today I got pissed at fstream, and made my own C stdio wrapper, apparently ios::app/ate doesn''t work with binary IO).

Share this post


Link to post
Share on other sites
Polymorphic's way is the one to use
Of course you might want to make the return type and the argument type of the function pointer something different :

struct logger
{
logger & operator <<( logger & (* arg)( logger & ) )
{
return arg( * this );
}
};
// endl example

logger & endl( logger & log )
{
log << "<br />";
log.flush();
return log;
}


Edit: make '\n' a <br />

[edited by - mputters on September 3, 2003 3:56:18 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by IFooBar
polymorphic: Your function parameter is exactly the same as my typedef except that I was using a TCHAR instead of a char. It also dosnt work. The compiler gives an error:


If you're getting an error then your compiler isnt compliant. Make sure you copied it correctly.

quote:
Original post by mputters
Of course you might want to make the return type and the argument type of the function pointer something different

But then you have to redefine endl and any other similar functions.

[edited by - Polymorphic OOP on September 3, 2003 4:19:45 AM]

Share this post


Link to post
Share on other sites
mputters: yeah your way works.

quote:
If you''re getting an error then your compiler isnt compliant. Make sure you copied it correctly.


The error has nothing to do with the function pointer decelration or compiler compliance. It happens when I pass endl to the logger. Your function pointer definition was fine. Like I said, same as the one I showed in my first post. The problem is that endl expects a stream object which the logger is not, that''s why it was giving the error.

though the problem with mputters way is

quote:
But then you have to redefine endl and any other similar functions.


But I guess that''s ok becuase I only really need to redefine endl and endp. So not a big problem. Cant seem to get it to work the "proper" way. It''s not like Ill be using std::endl/endp anyway.

thanks guys.

Share this post


Link to post
Share on other sites