473,394 Members | 1,715 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

ostream,stringstream and char*

Dear All,
I have the following piece of code:

---------------------------------------------
void f(const std::ostream &str)
{
std::ostringstream *pStr = (std::ostringstream*)(&str);
std::cout << pStr->str();
}
int main(int argc, char** argv)
{
//This works as expected
std::ostringstream str;
f(str << "Working example.\n"); //(1)

//And this prints some numbers (address of the pointer...)
f(std::ostringstream() << "This is not working\n"); //(2)

std::cout << std::endl;//new line

const char* const test = "TestVariable";

//this is the address of test:
printf("The address is: %p\n",test);

//and here we have the address again
f(std::ostringstream() << test);

std::cout << std::endl;//new line

//the address of test AND "some text" (?)
f(std::ostringstream() << test << "some text");//(3)

std::cout << std::endl;//new line

//and again, it works this way
std::ostringstream str2;
f(str2 << test);
}
-----------------------------------------------------

This is the output:
************************
Working example. <---(1)
0x446012 <---(2)
The address is: 0x446027
0x446027
0x446027some text <---(3)
TestVariable
************************

Can someone give me explanation why it is working for (1), and it is not
working for (2)?
Correct me if I'm wrong, but I thought that the bahaviour here would be
identical...
Also, the situation in (3) is strange for me.

I used cygwin (gcc 3.4.4) and Visual C++ 2003, for both compilers it looks
similar.

Thank you in advance for any help!

Best regards,
Protazy

Sep 1 '06 #1
6 14966
Protazy wrote:
void f(const std::ostream &str)
{
std::ostringstream *pStr = (std::ostringstream*)(&str);
std::cout << pStr->str();
}
You probably know that you shouldn't downcast and cast away constness
without good reason.
//And this prints some numbers (address of the pointer...)
f(std::ostringstream() << "This is not working\n"); //(2)
It boils down to the following test code:

#include <iostream>

using namespace std;

struct x
{
friend void operator << (x & lhs, char const* c)
{
cout << "friend" << endl;
}

void operator << (const void * p)
{
cout << "member" << endl;
}
};

int main()
{
x x_;
x_ << "x";
x() << "x";
}

prints:

friend
member

The reason being that (though I'm not sure where that's specified in the
standard, someone who knows might be so nice to point it out) non-const
member functions bind to temporaries, as your temporary
std::ostringstream. Free functions, such as my friend, which take
non-const references don't, so overload resolution in this case takes an
unexpected function. The standard specifies which operators should be
defined as members and which should be free, so it should be the same
behaviour on any platform.

Jens
Sep 1 '06 #2

Jens Theisen wrote:
Protazy wrote:
void f(const std::ostream &str)
{
std::ostringstream *pStr = (std::ostringstream*)(&str);
std::cout << pStr->str();
}

You probably know that you shouldn't downcast and cast away constness
without good reason.
You're right, my fault. Thanks for pointing that out.
>
The reason being that (though I'm not sure where that's specified in the
standard, someone who knows might be so nice to point it out) non-const
member functions bind to temporaries, as your temporary
std::ostringstream. Free functions, such as my friend, which take
non-const references don't, so overload resolution in this case takes an
unexpected function.
I think that - thanks to your explanations - I got it now. The ostringstream
does not have "<<" member operator for char*, but it has an operator for
void*, which is used here. And that's the reason for such behaviour. Tricky;>

Many thanks, I learned something valuable today.

Regards,
Protazy

Sep 1 '06 #3
Protazy wrote:
The ostringstream
does not have "<<" member operator for char*, but it has an operator for
void*, which is used here.
Oh, it does have! In your first example,

o << "Hello";

did the right thing, didn't it?

It's just that it's not found when you use it on a _temporary_. But in
real code you really don't want to use a temporary ostringstream in the
first place.

Jens
Sep 1 '06 #4

Jens Theisen wrote:
Protazy wrote:
The ostringstream
does not have "<<" member operator for char*, but it has an operator for
void*, which is used here.

Oh, it does have! In your first example,

o << "Hello";

did the right thing, didn't it?
From what I understood, it is not a member operator used here. It's a friend
function. Right?
What worries me is the bahaviour of:
f(std::ostringstream() << test << "some text");
In the first "<<" the member operator is used, but for second "<<" friend
function is invoked. Is the variable produced by first "<<" "less temporary"
then the variable produced by std::ostringstream()?

It's just that it's not found when you use it on a _temporary_. But in
real code you really don't want to use a temporary ostringstream in the
first place.
Why? Is it dangerous? I only need it to extract string from it. I want to do
something like:
f(std::stringstrem() << "The value is " << 2 << " and some object is " <<
someobject);
The variable should last long enough to be passed to the function. Or am I
missing something here?

Thanks and regards,
Protazy

Sep 2 '06 #5
Protazy wrote:
From what I understood, it is not a member operator used here. It's a friend
function. Right?
Sorry, I overlooked the "member". Yes it's a friend (or a non-friend
free function, depending on the implementation).
What worries me is the bahaviour of:
f(std::ostringstream() << test << "some text");
In the first "<<" the member operator is used, but for second "<<" friend
function is invoked. Is the variable produced by first "<<" "less temporary"
then the variable produced by std::ostringstream()?
Yes, it's less temporary. :)

The return value of operator << in this context is ostream &, which is a
non-const reference. In particular, it's an lvalue expression, where
std::ostringstream() is a temporary, ie. an rvalue expression. And
though what's returned by the first << operator expression is still the
same temporary, the expression is now an lvalue expression. lvalues bind
to non-const references, rvalues don't.

In this case, it seems weird and arbirtary, but usually it's what you
want since it's usually a programming error to pass an object by
reference (non-const, to modify it), if it's going to be destroyed after
the end of the expression. The essence of what happened in your example
is that it got explicitly casted to an lvalue.
Why? Is it dangerous? I only need it to extract string from it. I want to do
something like:
f(std::stringstrem() << "The value is " << 2 << " and some object is " <<
someobject);
Operator << on ostringstreams returns ostring&, so you can't call str on
it, that's why you made your f take an ostream and cast it down. While
legal, I don't really like it: The function is lying about what's it's
really accepting in it's signature, and somone who doesn't realise the
hack might put another kind of ostream in it at some point; which will
probably crash the program.

A better way is wrapping it into your own helper stream class:

struct make_string
{
template< typename T >
make_string & operator <<(T const& t)
{
m_s << t;
return *this;
}

operator std::string ()
{
return m_s.str();
}

private:
std::ostringstream m_s;
};

And then use it like

void foo(std::string const& str)
{
std::cout << str;
}

int main()
{
foo(make_string() << "Hello " << 42);
}

There is a more sophisticated class like this in boost, supporting
expressions like format("this: %1% and that: %2%") % these % those
(maybe the syntax is slightly different).
The variable should last long enough to be passed to the function. Or am I
missing something here?
Yes, it lasts long enough.

Jens
Sep 2 '06 #6

Jens Theisen wrote:
>
Yes, it's less temporary. :)

The return value of operator << in this context is ostream &, which is
Thanks for the explanations. And yes, it seems weird;-)
Operator << on ostringstreams returns ostring&, so you can't call str on
it, that's why you made your f take an ostream and cast it down. While
legal, I don't really like it: The function is lying about what's it's
really accepting in it's signature, and somone who doesn't realise the
hack might put another kind of ostream in it at some point; which will
probably crash the program.
In the final version I wanted to do a dynamic_cast<and check the return
value, so it would be safer.
>
A better way is wrapping it into your own helper stream class:
I also thought about it, I just wanted to know the reason for "strange"
ostringstream bahaviour. And now, thanks to you, I know:-)

Many thanks again!

Best regards,
Protazy

Sep 2 '06 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: joesoap | last post by:
Hi can anybody please tell me what is wrong with my ostream operator??? this is the output i get using the 3 attached files. this is the output after i run assignment2 -joesoap #include...
5
by: Ellarco | last post by:
Im sorry for asking a question that is surely in the archives somewhere, but I have been unable to locate it. Its about string memory management. I need to dynamically construct a C-style string...
4
by: David Johnstone | last post by:
Hi Group, I am using gcc 3.2.2 on linux 2.4.19-4GB (SuSe 8.2). I have a situation where I need to tie an ostringstream to an istringstream so I can write to one and read back what I wrote...
9
by: Ingo Nolden | last post by:
Hi there, I am writing c++ for some months now. I think I know the language now, but not yet all the tricky things of stl. For a kernel which is not using mfc I am writing a serialization. For...
5
by: cherico | last post by:
I'd like to read stings from cin and put them in stringstream. I use a string object as an intermediate "container" to store data from cin and then put them in stringstream. stringstream ss ;...
4
by: Vijai Kalyan | last post by:
I wrote the following function as a curiosity: template<typename SourceType, typename DestinationType> DestinationType NumericCast(const SourceType& value) { std::wstringstream strbuf; strbuf...
4
by: Rock | last post by:
I'm in the process of writing this program for complex numbers and I use DevC++. My professor on the other hand compiles on Borland 5.5. So I ocasionally save and run my work on Borland to see if...
1
by: FabioAng | last post by:
I implemented a codecvt facet (extracted from TCPL) but while it works well with 'ifstream' it doesn't work at all with 'stringstream'. Am I missing anything ? I tested it with MSVC 7.1 The code...
5
by: lars | last post by:
Hi, I have C (printf) style debug functions static void debugPrint(Silver::Strategy& s, unsigned level, const char *format, ...) { if (s.verbosityLevel() >= level ) { va_list args ;...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.