Re: concrete example on "inheriting" from ostream
Kanze, Thank you for the advice and codes, my code with your
modification is basically what I needed. I need to give it a try.
Meanwhile I have a couple of questions:
Typically, when you are wrapping an iostream, the operator<<
functions are member templates. Which shouldn't prevent you
from providing custom versions; all other things being equal,
overload resolution should prefer the non-template version (or
you can explicitly specialize the template function for the same
effect).
However in your example you use a template global fuction
operator<<(custom_ostream&, T const&).
[BTW, thank you for the clever tip of doing getStream();]
/** code **/ /** attention to the namespace qualifier, all this is
meant to be inside namespace latex**/
I'd definitly change the names. You're bound to encounter users
you do a "using namespace std;", and then all sorts of confusion
will result.
suggestions? I was thinking in changing latex::ofstream into
latex::document, however I didn't come out with a good replacemet for
latex::ostream without breaking the logical name pattern.
template< typename T >
latex::ostream&
operator<<( latex::ostream& dest, T const& obj )
{
dest.getStream() << obj ;
return dest ;
}
Thank you for this, my previous try was to put operator<< as a member
and that produced many problems, because member template had preference
over friend operator<<. However this is solved here.
latex::ostream&
operator<<( latex::ostream& dest,
std::ostream& (*manip)( std::ostream& ) )
{
dest.getStream() << manip ;
return dest ;
}
This solves the problem of being able of keep using the old good
manipulators. Thanks.
void set_math(){math_count_++; if(math_count_==1) os_<<"$";}
//technical issue with latex
void unset_math(){math_count_--; if(math_count_==0) os_<<"$";}
It would be nice to make the underlying buffer detect "$" character and
set the mathmode automatically. However this feature is too complicated
and probably overdesign.
struct FileBufWrapper
{
public:
FileBufWrapper( std::string const& filename,
std::ios::openmode mode )
{
myFilebuf.open( filename.c_str(), mode ) ;
}
streambuf* filebuf()
{
return &myFilebuf ;
}
private:
std::filebuf myFilebuf ;
} ;
class ofstream : private virtual FileBufWrapper,
public latex::ostream
{
Two quick questions here: why do we need a wrapper? why do we need
virtual inheritance?
Deriving private virtual from std::ofstream should work, but you
don't really need an ofstream, just a filebuf. Whence the
simple wrapper. (Deriving private virtual from std::filebuf
doesn't work, because you have no way of getting the address of
the subclass to pass it to latex::ostream. For some strange
reason, calling a member function on the constructed base object
is legal here, but converting the this pointer to the base
object type is undefined behavior---and doesn't work with at
least one compiler I've used.)
I am lost here. It makes sense to me to cast *this into a base class
type, even at construction time (anc even if the base class haven't
been initialized), but, who knows?, it may not make sense for the
compiler implementators.
Thank you, Alfredo
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]