 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
ricardw@axis.com Guest
|
Posted: Tue Nov 29, 2005 10:51 am Post subject: Problem with endl in derived streams |
|
|
Hi!
I've tried to find an answer to this in the FAQ and elsewhere on the
net, without success. I'm fairly sure that the issue must have turned
up before and that at least a handful of people may be able to point me
in the right direction.
Ok, I was trying to debug some code where endl appearantly wasn't
doing it's job, or at least, did not seem to be inserting an 'n' into
the stream. I managed to crystalize the problem area into this snippet:
#include <ostream>
#include <iostream>
#include <fstream>
using namespace std;
#define USE_OWN_ENDL (0)
class test_stream: public ofstream
{
public:
test_stream() {}
};
template <typename T> test_stream &operator<<(test_stream &s, T t)
{
std::cout << t;
return s;
}
#if USE_OWN_ENDL
test_stream &operator<<(test_stream &s, test_stream &(*fp)(test_stream
&))
{
return (*fp)(s);
}
test_stream &endl(test_stream &s)
{
std::cout << endl;
return s;
}
#endif
int main(int argc, char **argv)
{
cout << "Directly from main:n";
cout << "Hello world" << endl;
cout << "Hello again" << endl;
cout << "Using 'test_stream' class:n";
test_stream new_stream;
(new_stream << "Hello world") << endl;
(new_stream << "Hello again") << endl;
}
Now, as written (USE_OWN_ENDL is 0), the program does not output any
newlines to the new_stream. If I set USE_OWN_ENDL to 1, my own endl
function is invoked via the overloaded operator<<(test_stream&,
test_stream& (*fp)(test_stream&) call and it all works nicely. While
this is definitely possible, my guts are telling me there's a more
elegant way.
My feeling is that what is going on here is that since I've created my
own stream class, the base class operator<< does not come into play for
manipulators such as endl. Is it possible to define a suitable
operator<< that does this, so that I don't have to define my own endl?
I've tried various approaches that don't compile properly. Or is there
another approach to get this to work?
A related question: is this something that has changed in later years
because of a change in the standards or something? It seems to me that
the code I'm trying to work with must have worked (i.e. endls used as
described would have output 'n') at some time in some environment, and
it is only a couple of years old. So has endl worked in the way
expected because of a broken compiler or header file implementation at
some point?
Using g++ 3.3.5 (on Linux 2.6.8)
[Disclaimer: yes I know 'n' might be prefereble to endl, yes the
test_stream class doesn't do anything useful as it is written; I've
removed everything that's not related to the problem, the real class
adds some (slight) functionality to the stream]
/Ricard
|
|
| Back to top |
|
 |
Karl Heinz Buchegger Guest
|
Posted: Tue Nov 29, 2005 12:08 pm Post subject: Re: Problem with endl in derived streams |
|
|
[email]ricardw (AT) axis (DOT) com[/email] wrote:
| Quote: |
My feeling is that what is going on here is that since I've created my
own stream class, the base class operator<< does not come into play for
manipulators such as endl. Is it possible to define a suitable
operator<< that does this, so that I don't have to define my own endl?
I've tried various approaches that don't compile properly. Or is there
another approach to get this to work?
|
I can't answer your question.
But: The real question should be: Why do you want to derive
a new class from ofstream.
Usually that results in a lot of problems and is not necessary.
--
Karl Heinz Buchegger
[email]kbuchegg (AT) gascad (DOT) at[/email]
|
|
| Back to top |
|
 |
John Carson Guest
|
Posted: Tue Nov 29, 2005 12:31 pm Post subject: Re: Problem with endl in derived streams |
|
|
<ricardw (AT) axis (DOT) com> wrote
| Quote: | Hi!
I've tried to find an answer to this in the FAQ and elsewhere on the
net, without success. I'm fairly sure that the issue must have turned
up before and that at least a handful of people may be able to point
me in the right direction.
Ok, I was trying to debug some code where endl appearantly wasn't
doing it's job, or at least, did not seem to be inserting an 'n' into
the stream. I managed to crystalize the problem area into this
snippet:
#include <ostream
#include
#include
using namespace std;
#define USE_OWN_ENDL (0)
class test_stream: public ofstream
{
public:
test_stream() {}
};
template
{
std::cout << t;
return s;
}
#if USE_OWN_ENDL
test_stream &operator<<(test_stream &s, test_stream &(*fp)(test_stream
&))
{
return (*fp)(s);
}
test_stream &endl(test_stream &s)
{
std::cout << endl;
return s;
}
#endif
int main(int argc, char **argv)
{
cout << "Directly from main:n";
cout << "Hello world" << endl;
cout << "Hello again" << endl;
cout << "Using 'test_stream' class:n";
test_stream new_stream;
(new_stream << "Hello world") << endl;
(new_stream << "Hello again") << endl;
}
Now, as written (USE_OWN_ENDL is 0), the program does not output any
newlines to the new_stream. If I set USE_OWN_ENDL to 1, my own endl
function is invoked via the overloaded operator<<(test_stream&,
test_stream& (*fp)(test_stream&) call and it all works nicely. While
this is definitely possible, my guts are telling me there's a more
elegant way.
My feeling is that what is going on here is that since I've created my
own stream class, the base class operator<< does not come into play
for manipulators such as endl. Is it possible to define a suitable
operator<< that does this, so that I don't have to define my own endl?
I've tried various approaches that don't compile properly. Or is
there another approach to get this to work?
|
Based on my reading of Josuttis (The C++ Standard Library, pp. 612ff), it
seems that there is an overloaded operator<< for ostream that handles endl
and other manipulators. To get your code to work as you wish, it seems that
you simply need to modify your overload so it picks up the stream
manipulators that are already defined. This means that the function pointer
needs to be in terms of ostream, not test_stream.
The following works on your code, but robustness is not guaranteed.
test_stream &operator<<(test_stream &s, ostream &(*fp)(ostream &))
{
(*fp)(cout);
return s;
}
--
John Carson
|
|
| Back to top |
|
 |
ricardw@axis.com Guest
|
Posted: Wed Nov 30, 2005 7:41 am Post subject: Re: Problem with endl in derived streams |
|
|
Thanks John, that does fix the problem. Looking at it, it's almost too
obvious.
As for why the original stream class is derived from ofstream, well I
don't honestly know,
I'm just trying to get the code running again with as little effort as
possible (aren't we all .
/Ricard
|
|
| Back to top |
|
 |
Dietmar Kuehl Guest
|
Posted: Wed Nov 30, 2005 11:17 am Post subject: Re: Problem with endl in derived streams |
|
|
[email]ricardw (AT) axis (DOT) com[/email] wrote:
| Quote: | I've tried to find an answer to this in the FAQ and elsewhere on the
net, without success.
|
Exactly this question was discussed many times in this forum and
in comp.lang.c++.moderated. Searching e.g. for "endl derived stream"
on <http://groups.google.com/> turns up several useful results.
| Quote: | template <typename T> test_stream &operator<<(test_stream &s, T t)
{
std::cout << t;
return s;
}
|
This code is your problem: you *shall not* derive from 'std::ostream'
or its derived classes to change the output behavior! The *only*
reason to derive from 'std::ostream' is to create a convenience
interface for creating an 'std::ostream' with a derive stream buffer.
If you want to change the approach of output for a stream you shall
derive from 'std::streambuf'. Likewise for 'std::istream' and input.
More details and reasoning for this can easily be found by searching
past articles from me and/or James Kanze on the topic of stream
buffers.
--
<http://www.eai-systems.com> - Efficient Artificial Intelligence
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|