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 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
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
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.
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
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;
};
"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.
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.
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
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. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
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...
|
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";
|
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>
|
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);
|
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 ;
| |
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...
|
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");
|
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...
|
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?
|
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...
|
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...
| |
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...
|
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. ...
|
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...
|
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...
|
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...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
| |
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
|
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...
| |