473,585 Members | 2,512 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

tricky stringstream-based temporary

Hi folks,
I have trouble writing a class, derving from stringstream, that collects
item and once it's done will write them to std::cout in one go. It works
fine except when I use it as a temporary. Here is a tiny test programm:

#include <iostream>
#include <sstream>

class Gatherer : public std::stringstre am {
public:

~Gatherer ( void ) {
std::cout << this->str() << std::endl;
}

};

int main ( void ) {
{
Gatherer() << "hello world!";
}
{
Gatherer gather;
gather << "hello world!";
}
{
Gatherer() << std::dec << "hello world!";
}
}
On my machine, it prints:

0x8049e48
hello world!
hello world!

So, clearly the first line is an address. I have no explanation for this. I
am especially puzzled by the third line. Inserting a std::dec should not
have this effect, or should it?
Best regards

Kai-Uwe
Jul 22 '05 #1
19 2473
"Kai-Uwe Bux" <jk********@gmx .net> wrote...
I have trouble writing a class, derving from stringstream, that collects
item and once it's done will write them to std::cout in one go. It works
fine except when I use it as a temporary. Here is a tiny test programm:

#include <iostream>
#include <sstream>

class Gatherer : public std::stringstre am {
public:

~Gatherer ( void ) {
std::cout << this->str() << std::endl;
}

};

int main ( void ) {
{
Gatherer() << "hello world!";
}
{
Gatherer gather;
gather << "hello world!";
}
{
Gatherer() << std::dec << "hello world!";
}
}
On my machine, it prints:

0x8049e48
hello world!
hello world!

So, clearly the first line is an address. I have no explanation for this. I am especially puzzled by the third line. Inserting a std::dec should not
have this effect, or should it?


I think you're running into synchronisation problem. When compiled
with Intel v4.5 or VC++ v6sp5, this code outputs three hello. When
compiled with VC++ v7.1, it prints an address first and then two
hello, just like you described.

I think what you get is that by the time the destructor is executing,
all bets are off WRT the contents of this->str(), it may not contain
anything, or return a valid object... You might be incurring the UB.
Just a guess.

Victor
Jul 22 '05 #2
Victor Bazarov wrote:
"Kai-Uwe Bux" <jk********@gmx .net> wrote...
I have trouble writing a class, derving from stringstream, that collects
item and once it's done will write them to std::cout in one go. It works
fine except when I use it as a temporary. Here is a tiny test programm:

#include <iostream>
#include <sstream>

class Gatherer : public std::stringstre am {
public:

~Gatherer ( void ) {
std::cout << this->str() << std::endl;
}

};

int main ( void ) {
{
Gatherer() << "hello world!";
}
{
Gatherer gather;
gather << "hello world!";
}
{
Gatherer() << std::dec << "hello world!";
}
}
On my machine, it prints:

0x8049e48
hello world!
hello world!

So, clearly the first line is an address. I have no explanation for this.

I
am especially puzzled by the third line. Inserting a std::dec should not
have this effect, or should it?


I think you're running into synchronisation problem. When compiled
with Intel v4.5 or VC++ v6sp5, this code outputs three hello. When
compiled with VC++ v7.1, it prints an address first and then two
hello, just like you described.

I think what you get is that by the time the destructor is executing,
all bets are off WRT the contents of this->str(), it may not contain
anything, or return a valid object... You might be incurring the UB.
Just a guess.

Victor


Thanks for your help.

I eliminated inheritance as a possible source of the problem:

#include <fstream>

int main ( void ) {
std::ofstream( "greeting.o ut" ) << "hello world!\n";
}
This compiles fine. But it does unexpected things (well, as of now, I
actually was expecting this):

news_group> cat greeting.out
0x8048a01news_g roup>
So the problem definitely lies in the fact that a temporary is created.
Does the standard say that temporary streams have undefined behaviour? I
was under the impression that a temporary is supposed to behave exactly
like the real thing except that for its life time there are only very few
guarantees (like it will live at least to see the completion of the
expression of which it is a part).

As of now, I am considering the possibility that it could be a bug in my
standard library.
Thanks again

Kai-Uwe

Jul 22 '05 #3
Kai-Uwe Bux wrote:

int main ( void ) {
{
Gatherer() << "hello world!";
}
{
Gatherer gather;
gather << "hello world!";
}
{
Gatherer() << std::dec << "hello world!";
}
}


You're not supposed to pass a temporary for a non-const reference
parameter (in this case, the first parameter of operator<<). The result
of doing so is undefined.

--
Russell Hanneken
eu*******@cbobk .pbz
Use ROT13 to decode my email address.
Jul 22 '05 #4
Russell Hanneken wrote:
Kai-Uwe Bux wrote:

int main ( void ) {
{
Gatherer() << "hello world!";
}
{
Gatherer gather;
gather << "hello world!";
}
{
Gatherer() << std::dec << "hello world!";
}
}


You're not supposed to pass a temporary for a non-const reference
parameter (in this case, the first parameter of operator<<). The result
of doing so is undefined.


First off all: thank you. I was really puzzled.

Second: Could you direct me to the point in the standard where I find this.
I was just reading 12.2.5:

.... A temporary bound to a reference parameter in a function call (5.2.2)
persists until the completion of the full expression containing the call.
....

Wouldn't that have been a great place to put in a warnig? Please do not
get me wrong, I do not doubt that you are right -- I am just curious.
Thanks again

Kai-Uwe
Jul 22 '05 #5
Kai-Uwe Bux wrote:
{
Gatherer() << "hello world!";
}
Some background:

(1) When you call a function f(T()) then the function signature must be
either f(T) or f(const T&) but not f(T&). In other words, if the signature
is f(T&) then the argument cannot be a temporary.

(2) When you call a function T().f() then the function signature of T::f may
be either T::f() const or T::f(). In other words, you can call a non-const
member function on a temporary. This is a contrast to (1).

The reason my you see a number is that because of

Gatherer() <<

the compiler spots a temporary, and looks for member overloads
Gatherer::opera tor<< that match the function arguments. Now operator<<
const void* is implemented as a member, but operator<< const char * is
implemented as a non-member.

So while we wish the code calls

std::ostream<ch ar>& std::operator<< (ostream&, const char *);

it really calls only std::ostream::o perator<<(const void *);

As a QoI, a good compiler would probably look for both members and
non-members to call, and if it finds the non-member function is the right
one to call, issue an error or warning that the first argument cannot be a
temporary -- or at least issue an ambiguity between the two possible
operator<< to call.

So what you're seeing is the address of "hello world!". Try const char * s
= "hello world!" and then Gatherer() << s, followed by cout << (const void
*)(s), and see what happens
{
Gatherer gather;
gather << "hello world!";
}
Works as expected.
{
Gatherer() << std::dec << "hello world!";
}
}
Also works as expected. Fortunately Gatherer() << std::dec calls a member
function

basic_ostream:: operator<<(ios_ base& (*)(ios_base&))

and for member functions you are allowed to call non-const member functions
on a temporary. So this sets the decimal mode, returns an ostream&, adds
text to the ostream, and finally destroys the object and it prints what it
should.
You're not supposed to pass a temporary for a non-const reference
parameter (in this case, the first parameter of operator<<). The result
of doing so is undefined.


Right, but for the last case it's fine.
To the original problem, a possible solution is

class Gatherer : public std::stringstre am {
public:

~Gatherer ( void ) {
std::cout << d_stream.str() << std::endl;
}
template <class T>
Gatherer& operator<<(cons t T&);

private:
std::stringstre am d_stream;
};
Jul 22 '05 #6
"Victor Bazarov" <v.********@com Acast.net> wrote in message news:QX7yc.2123
I think you're running into synchronisation problem. When compiled
with Intel v4.5 or VC++ v6sp5, this code outputs three hello. When
compiled with VC++ v7.1, it prints an address first and then two
hello, just like you described.


MSVC7is more right than Intel or MSVC7. The compiler should never call the
non-member. The ideal compiler would give an error/warning.
Jul 22 '05 #7
Kai-Uwe Bux wrote:
Russell Hanneken wrote:

You're not supposed to pass a temporary for a non-const reference
parameter (in this case, the first parameter of operator<<). The result
of doing so is undefined.


Could you direct me to the point in the standard where I find this.


I couldn't find a place where it's stated directly. I think it's more
an implication of 8.5.3, section 5, which lists the valid ways to
initialize a reference. Temporaries just don't meet the qualifications
to be an initializer for a non-const reference.

Bjarne Stroustrup puts it pretty bluntly on page 98 of _The C++
Programming Language_: "The initializer for a 'plain' T& must be an
lvalue of type T."

--
Russell Hanneken
eu*******@cbobk .pbz
Use ROT13 to decode my email address.
Jul 22 '05 #8
Hi,
Thank you very much for this detailed explanation. Walking me through
the problem like that was more than I could have hoped for.
Best

Kai-Uwe
Jul 22 '05 #9
Siemel Naran wrote:
Gatherer() << std::dec << "hello world!";


Also works as expected. Fortunately Gatherer() << std::dec calls a member
function

basic_ostream:: operator<<(ios_ base& (*)(ios_base&))

and for member functions you are allowed to call non-const member functions
on a temporary. So this sets the decimal mode, returns an ostream&, adds
text to the ostream, and finally destroys the object and it prints what it
should.
You're not supposed to pass a temporary for a non-const reference
parameter (in this case, the first parameter of operator<<). The result
of doing so is undefined.


Right, but for the last case it's fine.


I don't follow this. The result of

Gatherer() << std::dec

is a reference to a temporary. So

(result of first expression) << "hello world!"

is an attempt to initialize a non-const reference parameter with a
temporary, which is still a problem, right?

--
Russell Hanneken
eu*******@cbobk .pbz
Use ROT13 to decode my email address.
Jul 22 '05 #10

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

Similar topics

2
5848
by: Bill Beacom | last post by:
Hi all, I am trying to use stringstream to assemble a text message from a set of user-defined objects that have the insertion operator overloaded. It seems to be putting them into the stringstream fine....however, I need to assemble it in "parts" (eg a prefix, a header, a body, a trailer and a checksum), and would like to reuse the...
2
7482
by: Woodster | last post by:
I am using std::stringstream to format a string. How can I clear the stringstream variable I am using to "re use" the same variable? Eg: Using std::string std::string buffer; buffer = "value1" + " : " + "value2";
3
14793
by: Mike Chirico | last post by:
Sorry about the newbie question. What's the best way to convert numbers to strings in C++. The following works, but is it better than using the sprintf() "old C" way of converting? #include <iostream> #include <string> #include <sstream> #include <list>
1
4890
by: KidLogik | last post by:
Hello! I am using std::stringstream && std::string to parse a text file -> std::ifstream in; std::string s; std::streamstring ss; int n; I grab each line like so -> std::getline(in,s);
5
10858
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 ; string str ; cin >> str ; ss << str ;
5
817
by: William Payne | last post by:
How do you get rid the contents in a std::stringstream? I'm using one in a for loop to format some status messages which I print to the screen. The stringstream member function clear() only clears flags (bits) in the stream, right? I solved it by declaring the stringstream inside the loop body even though I have need of another stringstream...
9
5511
by: martinezfive | last post by:
Hi, I feel no doubt some documentation contains my answer, so bare with me. Given the following: #inclde <stdio.h> #include <sstream> void f() { std::stringstream a("Hello World!\n");
7
3598
by: Ziyan | last post by:
I am writing a C/C++ program that runs in background (Linux). Therefore, normally no output would be written into standard output. However, sometimes I want to have debug message collected and sent tho network to a client so that errors and debug messages can be displayed simultaneously anywhere. I tried to use a std::stringstream to do the...
4
2644
by: clb | last post by:
I am trying to use stringstreams and my book doesn't cover the included methods. For example, if I init a istringstream on a string and suck all the data out, then put more stuff into the string, how do I reset the ISS to see the new data? Does this make sense?
4
1857
by: mthread | last post by:
Hi, I am using a string variable in which I do lot of appending. The only difficulty I am facing as of now is appending a integer/float value to this variable. Although I can accomplish this task using a stringstream variable, it makes my life difficult as it involves 2 function call(one for adding the information to stringstream variable...
0
7908
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7836
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
8199
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8336
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
5710
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
3835
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3863
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1447
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
1175
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

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.