Re: concrete example on "inheriting" from ostream
Thank for the answers so far. After reading them I wrote a code which I
think is clear but still have some (minor?) problems.
I think all you noticed that I have a superficial view of what
std::streams are (sometimes this is good.)
Formaters and/or custom manipulators are good and I had been using them
before; that may do part of the job.
However I was looking for a more drastic format change associated
explicitly with the kind of output sink (let's stop calling output
stream to not confuse with it with the std::ostream classes)
OK, I will be specific with the objective: I wanted to output many
types to a LaTeX source file (sorry for those not familiar with LaTeX).
Some of these types are mathematical structures that need something
better than a dumb terminal for output and specially debugging.
(although I still wanted to keep and define some quick printing
routines in case the only available output is a terminal)
so I wanted something that worked like this:
latex::ofstream lout("file.tex");
lout<<int(9)<<" hello "<<std::complex<double>(2,3)<<"
"<<custom_class_with_mathematical_structure()<<std::endl;
file.tex will then contain a latex document source, following the
proper latex format so express this numbers and character strings.
Another way of looking at the problem is that this custom_classes will
be smart and know that when they are printed to a "latex sink" they can
express them selves in a full mathematical-structured way, while for
simple types the changes in the format are just slight or absent. At
the same time this custom_classes will output to simplified text
versions if the sink is a std::ostream (such as std::cout).
Some solutions I tried:
1) Inheriting from ostream caused problems because operator<< are not
virtual in std::ostream and cause ambiguity if I want to customize it.
[So I decided to put std::ostream as a member of latex::ostream (sorry
for duplicated names)]
2) automatizing the compile time generation of template<typename T>
operator<<(T t) to keep the default behavior of std::ostream didn't
work because then any friend operator<<(latex::ostream&, type const&)
[which I wanted to define inside custom classes] then will conflict
with the template member function mentioned.
currently the design is the following code. The only problem right now
is that I can't control the initialization order of the base class
ostream and member std::ofstream in the class ofstream. (I am very
sorry by the similar names) This initialization order gives a warning
in gcc-4 which I would like to get rid off. I somewhere read that
private virtual inheritance sometimes is a solution to force
initialization order of base relative to members but I didn't manage to
make it work. Here is the code:
/** code **/ /** attention to the namespace qualifier, all this is
meant to be inside namespace latex**/
class ostream{
std::ostream os_;
public:
ostream(std::streambuf* buf) : os_(buf), math_count_(0) {}
ostream(std::ostream& os) : os_(os.rdbuf()), math_count_(0) {}
virtual ~ostream(){}
ostream& operator<<(int i ){os_<<i ; return *this;}
ostream& operator<<(char c ){os_<<c ; return *this;}
ostream& operator<<(char* const cs){os_<<cs; return *this;}
ostream& operator<<(double d ){os_<<d<<'.'; return *this;}
ostream& operator<<(std::complex<double> const& c); //defined
later to output eg. 3+2i
void set_math(){math_count_++; if(math_count_==1) os_<<"$";}
//technical issue with latex
void unset_math(){math_count_--; if(math_count_==0) os_<<"$";}
private:
int math_count_;
};
class ofstream : public ostream{
std::ofstream ofs_;
public:
ofstream(std::string const& filename) :
ofs_(filename.c_str()), // <- WARNING HERE
ostream(ofs_.rdbuf()){
ofs_<<("\\documentclass[12pt]{article}")<<std::endl;
ofs_<<("\\begin{document}")<<std::endl;
}
virtual ~ofstream(){
ofs_<<("\\end{document}")<<std::endl;
}
};
/** end of code **/
Suggestions for solving the warning are welcome, other alternatives are
welcomed. Thoughts about whether the warning can be pointing to a
serious problem are also welcomed.
Alfredo.
PS: this is not a homework assignement (as somebody suggested)
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]