ostringstream and write()

R

roberts.noah

Using ostringstream the buffer gets increased to allow data to be
appended when needed at least when you call <<. I was under the
impression that write() also did but I am having problems that make me
doubt that. Can I depend on the behavior of something like this?

ostringstream os;

os.write("This is a test.", strlen("This is a test."));
cout << os.str() << endl;

If so my problem is obviously caused by something else...
 
R

roberts.noah

Using ostringstream the buffer gets increased to allow data to be
appended when needed at least when you call <<. I was under the
impression that write() also did but I am having problems that make me
doubt that. Can I depend on the behavior of something like this?

ostringstream os;

os.write("This is a test.", strlen("This is a test."));
cout << os.str() << endl;

If so my problem is obviously caused by something else...

I realized what the problem was. I was using iostream as a polymorphic
entity and it isn't. Code above would have looked more like this
logically invalid code:

ostringstream os;
ostream * ptr = &os;

ptr->write("This is a test.", strlen("This is a test."));

This of course does not work because templates don't have virtual
functions and streams are templates. I was being stupid again.
 
R

Rolf Magnus

I realized what the problem was. I was using iostream as a polymorphic
entity and it isn't.

How did you get that idea? iostreams are polymorphic.
Code above would have looked more like this logically invalid code:

ostringstream os;
ostream * ptr = &os;

ptr->write("This is a test.", strlen("This is a test."));

This of course does not work because templates don't have virtual
functions and streams are templates.

Again, this is a false assumption. What makes you think that a class
template cannot have virtual functions?
 
R

roberts.noah

Rolf said:
How did you get that idea? iostreams are polymorphic.

In order for a class to be polymorphic it has to have virtual
functions. The iostreams in the std lib do not. They are therefore
not polymorphic.

If you doubt this then just do what I did: Call write() on a
stringstream from a pointer to type iostream and see what happens.
Again, this is a false assumption. What makes you think that a class
template cannot have virtual functions?

It was either in the book "Generic Programming" or "Template
Metaprogramming" that I first read this; I believe in the former as it
is part of the reasoning behind policies. Tests with my compiler
generate errors. There is also a discussion on comp.lang.c++.moderated
entitled "Why a template function cannot be a virtual function?". I
would paste a link but copy paste has decided not to work and I will
probably now have to reboot my computer. You should be able to find it
yourself with the title.
 
P

Pete C

Code above would have looked more like this
logically invalid code:

ostringstream os;
ostream * ptr = &os;

ptr->write("This is a test.", strlen("This is a test."));

This of course does not work because templates don't have virtual
functions and streams are templates. I was being stupid again.

No, that code is absolutely fine. Your problem must lie somewhere else.
 
R

Richard Herring

In order for a class to be polymorphic it has to have virtual
functions.

In order for a class to be polymorphic all it needs is to have derived
classes. It's only to make RTTI and dynamic_cast work that it has to
have virtual functions.
The iostreams in the std lib do not. They are therefore
not polymorphic.

If you doubt this then just do what I did: Call write() on a
stringstream from a pointer to type iostream and see what happens.

#include <iostream>
#include <ostream>
#include <sstream>

int main()
{
std::eek:stringstream s;
std::eek:stream * p = &s;
p->write("abcdefg", 7);
std::cout << s.str() << '\n';
}

writes this for me:

abcdefg

I think your problem is elsewhere.
 
R

roberts.noah

Richard said:
In message <[email protected]>,
(e-mail address removed) writes

In order for a class to be polymorphic all it needs is to have derived
classes. It's only to make RTTI and dynamic_cast work that it has to
have virtual functions.

If you say so. I'll believe the language standard and common use of
the term though.
#include <iostream>
#include <ostream>
#include <sstream>

int main()
{
std::eek:stringstream s;
std::eek:stream * p = &s;
p->write("abcdefg", 7);
std::cout << s.str() << '\n';
}

writes this for me:

abcdefg

I think your problem is elsewhere.

Yes it does. streambuf is polymorphic (its public interface calls
protected virtual members). Removing the abstract reference fixed my
problem and since streams are NOT polymorphic it tricked me. At this
point it doesn't matter...some change I made along the line fixed it
because the abstract reference now functions.
 
R

Rolf Magnus

In order for a class to be polymorphic it has to have virtual
functions.
Right.

The iostreams in the std lib do not.

Again, this is _not_ true. They do have virtual member functions.
They are therefore not polymorphic.

If you doubt this

I don't just doubt it. I know it's wrong.
then just do what I did: Call write() on a stringstream from a pointer to
type iostream and see what happens.

#include <iostream>

int main()
{
std::stringstream stream;
std::iostream* p = &stream;
p->write("x\n", 2);
std::cout << stream.str();
}

The output of the above program on my computer is:

x

That's exactly what I expect.
It was either in the book "Generic Programming" or "Template
Metaprogramming" that I first read this; I believe in the former as it
is part of the reasoning behind policies. Tests with my compiler
generate errors.

How did you test? Try this:

#include <iostream>

template<typename T>
class Base
{
public:
virtual void test()
{
std::cout << "This is Base<>::test()\n";
}
};

template<typename T>
class Derived : public Base<T>
{
public:
void test()
{
std::cout << "This is Derived<>::test()\n";
}
};

int main()
{
Derived<char> d;
Base<char>* p = &d;
p->test();
}
There is also a discussion on comp.lang.c++.moderated entitled "Why a
template function cannot be a virtual function?".

A function template cannot be virtual, but a normal member function of a
class template can.
 
R

Rolf Magnus

In order for a class to be polymorphic it has to have virtual
functions.
Right.

The iostreams in the std lib do not.

Ok, maybe only the streambufs, not the streams themselves. Not sure about
this.
They are therefore not polymorphic.

If you doubt this then just do what I did: Call write() on a stringstream
from a pointer to type iostream and see what happens.

#include <iostream>

int main()
{
std::stringstream stream;
std::iostream* p = &stream;
p->write("x\n", 2);
std::cout << stream.str();
}

The output of the above program on my computer is:

x

That's exactly what I expect.
It was either in the book "Generic Programming" or "Template
Metaprogramming" that I first read this; I believe in the former as it
is part of the reasoning behind policies. Tests with my compiler
generate errors.

How did you test? Try this:

#include <iostream>

template<typename T>
class Base
{
public:
virtual void test()
{
std::cout << "This is Base<>::test()\n";
}
};

template<typename T>
class Derived : public Base<T>
{
public:
void test()
{
std::cout << "This is Derived<>::test()\n";
}
};

int main()
{
Derived<char> d;
Base<char>* p = &d;
p->test();
}
There is also a discussion on comp.lang.c++.moderated entitled "Why a
template function cannot be a virtual function?".

A function template cannot be virtual, but a normal member function of a
class template can.
 
R

Richard Herring

If you say so. I'll believe the language standard and common use of
the term though.

OK, I'll rephrase that. You are correct about the definition of
polymorphism, but the whole issue of polymorphism is a red herring and
what you were really talking about, access to a base class using a
pointer to a derived class, is not polymorphism, and doesn't need
virtual functions to exist:

4.10/3 An rvalue of type "pointer to cv D", where D is a class type,
can be converted to type "pointer to cv B", where B is a base class of
D. [...] The result of the conversion is a pointer to the base class
sub-object of the derived class object.
 
R

roberts.noah

Richard said:
OK, I'll rephrase that. You are correct about the definition of
polymorphism, but the whole issue of polymorphism is a red herring and
what you were really talking about, access to a base class using a
pointer to a derived class, is not polymorphism, and doesn't need
virtual functions to exist:

No, it is not polymorphism. Calls made to overriden members of
non-virtual functions result in the call being made to the parent type.
If the overridden members need to do such things as bounds checking on
an internal buffer before doing the stuff normally performed by the
function ... and that stuff is not done because the function called was
the one belonging to the parent ... then you have problems.

Such a design obviously has problems, which is why streams work off of
buffers that ARE polymorphic.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top