From: K. F. <kfr...@gm...> - 2011-03-22 02:55:07
|
Hello List! Sorry I couldn't think of a more informative subject, but that's because I don't understand what's going on. Specifically, the following expression doesn't evaluate as I expect. dynamic_cast<std::stringstream&>(std::stringstream() << "xyz").str() It appears as if "xyz" is getting inserted into the temporary stringstream as a pointer rather than as a character string. If I replace the temporary stringstream with a named local-variable stringstream, it works as I expect. If I insert an integer literal rather than a string literal into the temporary stringstream, it also works as I expect. Is this a compiler bug, or am I wrong in expecting the temporary stringstream and the named local variable to behave the same? Here is a short example program that illustrates the issue: << stringstream_cast.cpp >> #include <iostream> #include <sstream> #include <typeinfo> int main (int argc, char *argv[]) { std::stringstream sstr1; sstr1 << "abc"; std::string s1 = sstr1.str(); std::cout << "expecting abc: " << s1 << std::endl; std::stringstream sstr2; std::string s2 = dynamic_cast<std::stringstream&>(sstr2 << "ijk").str(); std::cout << "expecting ijk: " << s2 << std::endl; std::string s3 = dynamic_cast<std::stringstream&>(std::stringstream() << "xyz").str(); std::cout << "expecting xyz: " << s3 << std::endl; // prints out a hex value -- treating "xyz" as a pointer? std::string s4 = dynamic_cast<std::stringstream&>(std::stringstream() << 123).str(); std::cout << "expecting 123: " << s4 << std::endl; } Here is the compile command and the output: C:\>g++ --version g++ (TDM-2 mingw32) 4.4.1 Copyright (C) 2009 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. C:\>g++ -o stringstream_cast stringstream_cast.cpp C:\>stringstream_cast expecting abc: abc expecting ijk: ijk expecting xyz: 0x47704c expecting 123: 123 Any insight into what is going on here would be appreciated. Thanks. K. Frank |
From: Greg C. <gch...@sb...> - 2011-03-22 13:54:09
|
On 2011-03-22 02:55Z, K. Frank wrote: > > Specifically, the following expression doesn't evaluate as I expect. > > dynamic_cast<std::stringstream&>(std::stringstream() << "xyz").str() I see a similar outcome running your testcase with Comeau C/C++ 4.3.10.1 and MinGW gcc-3.4.5 . > It appears as if "xyz" is getting inserted into the temporary stringstream > as a pointer rather than as a character string. I immediately thought of the "most vexing parse", but that doesn't seem to explain the anomaly--adding extra parentheses: dynamic_cast<std::stringstream&>((std::stringstream()) << ("xyz")).str(); has no effect, and the dynamic_cast does succeed. What's printed is certainly the address of the string literal, because this code prints the same address twice: char const p[] = "rst"; std::string s3a = dynamic_cast<std::stringstream&>(std::stringstream() << p).str(); std::cout << "expecting rst: " << s3a << std::endl; std::cout << "addr of 'p': " << &p << std::endl; > If I replace the temporary > stringstream with a named local-variable stringstream, it works as I > expect. If I insert an integer literal rather than a string literal into the > temporary stringstream, it also works as I expect. This "works": std::string s3 = dynamic_cast<std::stringstream&>(std::stringstream() << std::skipws << "xyz").str(); It looks silly, but 'skipws' should have no effect on output. > Is this a compiler bug, or am I wrong in expecting the temporary > stringstream and the named local variable to behave the same? I don't know. Comeau C++ behaves the same way, and it's an excellent compiler; but if the problem lies in the standard library, then it's just using a modernized version of the same ancient HP code that everyone started with. Here's one more example that can be dropped into your testcase: std::string s("uvw"); std::string s3b = dynamic_cast<std::stringstream&>(std::stringstream() << s).str(); std::cout << "expecting uvw: " << s3b << std::endl; That succeeds with Comeau (but prints the pointer address), but fails with MinGW gcc-3.4.5: no match for 'operator<<' in 'stringstream(std::operator|( _S_out, _S_in)) << s' and 'stringstream(std::operator|( _S_out, _S_in))' sure looks like a constructor rather than a constructed object--and that does look like the "most vexing parse". The 'skipws' trick above makes it behave as we expect. If you find the answer elsewhere, please mention it here. |
From: K. F. <kfr...@gm...> - 2011-03-22 14:50:58
|
Hi Greg! Thank you for your feedback. On Tue, Mar 22, 2011 at 9:53 AM, Greg Chicares <gch...@sb...> wrote: > On 2011-03-22 02:55Z, K. Frank wrote: >> >> Specifically, the following expression doesn't evaluate as I expect. >> >> dynamic_cast<std::stringstream&>(std::stringstream() << "xyz").str() > > I see a similar outcome running your testcase with Comeau C/C++ 4.3.10.1 > and MinGW gcc-3.4.5 . I had also tried my code with the Comeau online compiler. It compiled, but as the online compiler doesn't link or run, I couldn't see the code's behavior. I also ran a version 4.5 g++, with the same result. >> It appears as if "xyz" is getting inserted into the temporary stringstream >> as a pointer rather than as a character string. > > I immediately thought of the "most vexing parse", Yeah, I did too, but I really don't think it applies here. > but that doesn't seem > to explain the anomaly--adding extra parentheses: > dynamic_cast<std::stringstream&>((std::stringstream()) << ("xyz")).str(); > has no effect, and the dynamic_cast does succeed. > ... > This "works": > std::string s3 = dynamic_cast<std::stringstream&>(std::stringstream() << std::skipws << "xyz").str(); > It looks silly, but 'skipws' should have no effect on output. Thanks for that data point. It probably offers a clue as to what is going on, but I don't know how the internals of iostream work, so nothing specific comes to mind. > ... > Here's one more example that can be dropped into your testcase: > > std::string s("uvw"); > std::string s3b = dynamic_cast<std::stringstream&>(std::stringstream() << s).str(); > std::cout << "expecting uvw: " << s3b << std::endl; > > That succeeds with Comeau (but prints the pointer address), but fails > with MinGW gcc-3.4.5: > no match for 'operator<<' in 'stringstream(std::operator|( _S_out, _S_in)) << s' > and 'stringstream(std::operator|( _S_out, _S_in))'... Yes, I tried the same thing (but with an unnamed temporary std::string), and got a similar compile-time error with mingw 4.4. Interesting that it compiles with Comeau, but runs "incorrectly." > sure looks like a > constructor rather than a constructed object--and that does look like > the "most vexing parse". The 'skipws' trick above makes it behave as > we expect. Hmm... I think I have an msvc installed somewhere. I'll give that a try. I'll also try it on linux g++, but I doubt I'll see any difference. This seems like a gcc issue, rather than anything specific to mingw. > If you find the answer elsewhere, please mention it here. Yes, I will. I'm betting on a compiler error (or, more precisely, a library error), especially with the skipws and integer-literal insertions working correctly. (Well, I suppose my code could be in error somehow, leading to that last refuge of compiler-writing scoundrels -- undefined behavior. But it sure looks legal to me.) Thank again for taking a look at this. K. Frank |
From: K. F. <kfr...@gm...> - 2011-03-23 02:15:54
|
Hello Greg! On Tue, Mar 22, 2011 at 10:50 AM, K. Frank <kfr...@gm...> wrote: > Hi Greg! > > Thank you for your feedback. > > On Tue, Mar 22, 2011 at 9:53 AM, Greg Chicares <gch...@sb...> wrote: >> On 2011-03-22 02:55Z, K. Frank wrote: >>> >>> Specifically, the following expression doesn't evaluate as I expect. >>> >>> dynamic_cast<std::stringstream&>(std::stringstream() << "xyz").str() >> ... >>> It appears as if "xyz" is getting inserted into the temporary stringstream >>> as a pointer rather than as a character string. >> ... One more data point: I see the same behavior with msvc9, in that the pointer value (address) is printed out rather than "xyz". >> ... >> This "works": >> std::string s3 = dynamic_cast<std::stringstream&>(std::stringstream() << std::skipws << "xyz").str(); >> It looks silly, but 'skipws' should have no effect on output. Adding skipws also "works" with msvc9 (in that "xyz" is printed out). >> ... >> Here's one more example that can be dropped into your testcase: >> >> std::string s("uvw"); >> std::string s3b = dynamic_cast<std::stringstream&>(std::stringstream() << s).str(); >> std::cout << "expecting uvw: " << s3b << std::endl; >> >> That succeeds with Comeau (but prints the pointer address),... This compiles with msvc9 and prints out "uvw". >> ... > Hmm... > > I think I have an msvc installed somewhere. I'll give that a try. > I'll also try it on linux g++, but I doubt I'll see any difference. > This seems like a gcc issue, rather than anything specific to > mingw. So, as you see above, I did try it with msvc9. To summarize, all of the various test cases compiled, and all worked as expected (printing out the string), with the exception of the "base case" dynamic_cast<std::stringstream&>(std::stringstream() << "xyz").str() which printed out the pointer value. I haven't tried it on linux yet. >> If you find the answer elsewhere, please mention it here. I haven't found the answer yet. So what are people's thoughts? Is this a case of incorrect code, or is this a compiler (library) error? To me, the code looks good, but we now have three compiler families (g++, comeau, and msvc) all printing out the pointer value rather than the string in the base case (but not fully agreeing in at least one of the other cases), maybe suggesting that problem lies with the code -- or with my expectations. Although as Greg said, if the libraries derive from a common code base, they could all be sharing the same error. > ... Any further thoughts or test results would be appreciated. Thanks. K. Frank |
From: Alexander S. <ash...@gm...> - 2011-03-23 11:19:57
|
Hello, On Tue, 22 Mar 2011 22:15:46 -0400 K. Frank wrote: > Any further thoughts or test results would be appreciated. Maybe you could ask this question at stackoverflow.com? After all, it's the kind of site where people ask this kind of questions There are more C++ experts there than here, I think (I even saw some posts by Stroustrup there). I'm interested why this problem happens as well. Cheers, Alexander |
From: Greg C. <gch...@sb...> - 2011-03-23 11:35:47
|
On 2011-03-23 02:15Z, K. Frank wrote: > > To me, the code looks good, but we now have three compiler > families (g++, comeau, and msvc) all printing out the pointer > value rather than the string in the base case (but not fully > agreeing in at least one of the other cases), maybe suggesting > that problem lies with the code -- or with my expectations. > > Although as Greg said, if the libraries derive from a common > code base, they could all be sharing the same error. IIRC, years ago ms used their own C++ standard library, but now they use a modified version of dinkumware's... http://www.dinkumware.com/cpp.aspx | Among many other compiler vendors, Microsoft and IBM ship customized | versions of this library with their C++ compiler products. ...which apparently was written from scratch... http://www.dinkumware.com/competitors.aspx | We write all our own software and distribute no software encumbered | by any form of open-source license restrictions. ...and which claims superior conformance, probably with good cause, though it's in their commercial interest to state their case strongly: http://www.dinkumware.com/tr1_compare.aspx So it seems that we have a couple of very different standard libraries, and several very different compilers, all of which do something we can't explain. Maybe they're right and we just haven't found the explanation. |
From: Kai T. <kti...@go...> - 2011-03-23 11:46:20
|
2011/3/23 Greg Chicares <gch...@sb...>: > On 2011-03-23 02:15Z, K. Frank wrote: >> >> To me, the code looks good, but we now have three compiler >> families (g++, comeau, and msvc) all printing out the pointer >> value rather than the string in the base case (but not fully >> agreeing in at least one of the other cases), maybe suggesting >> that problem lies with the code -- or with my expectations. >> >> Although as Greg said, if the libraries derive from a common >> code base, they could all be sharing the same error. > > IIRC, years ago ms used their own C++ standard library, but now they > use a modified version of dinkumware's... > > http://www.dinkumware.com/cpp.aspx > | Among many other compiler vendors, Microsoft and IBM ship customized > | versions of this library with their C++ compiler products. > > ...which apparently was written from scratch... > > http://www.dinkumware.com/competitors.aspx > | We write all our own software and distribute no software encumbered > | by any form of open-source license restrictions. > > ...and which claims superior conformance, probably with good cause, > though it's in their commercial interest to state their case strongly: > > http://www.dinkumware.com/tr1_compare.aspx > > So it seems that we have a couple of very different standard libraries, > and several very different compilers, all of which do something we can't > explain. Maybe they're right and we just haven't found the explanation. > > ------------------------------------------------------------------------------ > Enable your software for Intel(R) Active Management Technology to meet the > growing manageability and security demands of your customers. Businesses > are taking advantage of Intel(R) vPro (TM) technology - will your software > be a part of the solution? Download the Intel(R) Manageability Checker > today! http://p.sf.net/sfu/intel-dev2devmar > _______________________________________________ > MinGW-users mailing list > Min...@li... > > This list observes the Etiquette found at > http://www.mingw.org/Mailing_Lists. > We ask that you be polite and do the same. Disregard for the list etiquette may cause your account to be moderated. > > _______________________________________________ > You may change your MinGW Account Options or unsubscribe at: > https://lists.sourceforge.net/lists/listinfo/mingw-users > Also: mailto:min...@li...?subject=unsubscribe > Well, AFAICS is the issue that standard c++ doesn't supports this. It is a c++0x standard thing and works perfectly by using 4.6.0 toolchain. It might work with 4.5.x too. I just don't have such a toolchain right now at hand. But try to use here option -std=c++0x. Regards, Kai |
From: david <da...@fi...> - 2011-03-23 15:12:57
|
Isn't casting a temporary object to a non const reference yielding undefined behaviour? See as well here: http://bytes.com/topic/c/answers/132320-cast-non-const-reference-functions-return-object > On 2011-03-22 02:55Z, K. Frank wrote: >> Specifically, the following expression doesn't evaluate as I expect. >> >> dynamic_cast<std::stringstream&>(std::stringstream()<< "xyz").str() > I see a similar outcome running your testcase with Comeau C/C++ 4.3.10.1 > and MinGW gcc-3.4.5 . > >> It appears as if "xyz" is getting inserted into the temporary stringstream >> as a pointer rather than as a character string. > I immediately thought of the "most vexing parse", but that doesn't seem > to explain the anomaly--adding extra parentheses: > dynamic_cast<std::stringstream&>((std::stringstream())<< ("xyz")).str(); > has no effect, and the dynamic_cast does succeed. > > What's printed is certainly the address of the string literal, because > this code prints the same address twice: > > char const p[] = "rst"; > std::string s3a = dynamic_cast<std::stringstream&>(std::stringstream()<< p).str(); > std::cout<< "expecting rst: "<< s3a<< std::endl; > std::cout<< "addr of 'p': "<< &p<< std::endl; > >> If I replace the temporary >> stringstream with a named local-variable stringstream, it works as I >> expect. If I insert an integer literal rather than a string literal into the >> temporary stringstream, it also works as I expect. > This "works": > std::string s3 = dynamic_cast<std::stringstream&>(std::stringstream()<< std::skipws<< "xyz").str(); > It looks silly, but 'skipws' should have no effect on output. > >> Is this a compiler bug, or am I wrong in expecting the temporary >> stringstream and the named local variable to behave the same? > I don't know. Comeau C++ behaves the same way, and it's an excellent > compiler; but if the problem lies in the standard library, then it's > just using a modernized version of the same ancient HP code that > everyone started with. > > Here's one more example that can be dropped into your testcase: > > std::string s("uvw"); > std::string s3b = dynamic_cast<std::stringstream&>(std::stringstream()<< s).str(); > std::cout<< "expecting uvw: "<< s3b<< std::endl; > > That succeeds with Comeau (but prints the pointer address), but fails > with MinGW gcc-3.4.5: > no match for 'operator<<' in 'stringstream(std::operator|( _S_out, _S_in))<< s' > and 'stringstream(std::operator|( _S_out, _S_in))' sure looks like a > constructor rather than a constructed object--and that does look like > the "most vexing parse". The 'skipws' trick above makes it behave as > we expect. > > If you find the answer elsewhere, please mention it here. > > ------------------------------------------------------------------------------ > Enable your software for Intel(R) Active Management Technology to meet the > growing manageability and security demands of your customers. Businesses > are taking advantage of Intel(R) vPro (TM) technology - will your software > be a part of the solution? Download the Intel(R) Manageability Checker > today! http://p.sf.net/sfu/intel-dev2devmar > _______________________________________________ > MinGW-users mailing list > Min...@li... > > This list observes the Etiquette found at > http://www.mingw.org/Mailing_Lists. > We ask that you be polite and do the same. Disregard for the list etiquette may cause your account to be moderated. > > _______________________________________________ > You may change your MinGW Account Options or unsubscribe at: > https://lists.sourceforge.net/lists/listinfo/mingw-users > Also: mailto:min...@li...?subject=unsubscribe |
From: Kai T. <kti...@go...> - 2011-03-23 15:27:48
|
2011/3/23 david <da...@fi...>: > > Isn't casting a temporary object to a non const reference yielding > undefined behaviour? > See as well here: > http://bytes.com/topic/c/answers/132320-cast-non-const-reference-functions-return-object Yes, you are right. But this seems not to be for c++0x. At least I think in 12.2.5+ the mention just references and not const ones only. see: 5 The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except: — A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits. — 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. --- the lifetime of a temporary bound to the returned value in a function return statement (6.6.3) is not extended; the temporary is destroyed at the end of the full-expression in the return statement. — A temporary bound to a reference in a new-initializer (5.3.4) persists until the completion of the full-expression containing the new-initializer. [ Note: This may introduce a dangling reference, and implementations are encouraged to issue a warning in such a case. —end note ] The destruction of a temporary whose lifetime is not extended by being bound to a reference is sequenced before the destruction of every temporary which is constructed earlier in the same full-expression. If the lifetime of two or more temporaries to which references are bound ends at the same point, these temporaries are destroyed at that point in the reverse order of the completion of their construction. In addition, the destruction of temporaries bound to references shall take into account the ordering of destruction of objects with static, thread, or automatic storage duration (3.7.1, 3.7.2, 3.7.3); that is, if obj1 is an object with the same storage duration as the temporary and created before the temporary is created the temporary shall be destroyed before obj1 is destroyed; if obj2 is an object with the same storage duration as the temporary and created after the temporary is created the temporary shall be destroyed after obj2 is destroyed. But well, I might be wrong by my reading here. Kai |
From: K. F. <kfr...@gm...> - 2011-03-24 16:16:22
|
Hello Language Lawyers! I posted this question about the stringstream temporary to the usenet group comp.lang.c++. You can find it, for example, here: http://groups.google.com/group/comp.lang.c++/browse_thread/thread/c52862ddde8daaf6# Maybe someone over there will have some wisdom to offer. On Wed, Mar 23, 2011 at 11:27 AM, Kai Tietz <kti...@go...> wrote: > 2011/3/23 david <da...@fi...>: >> ... Happy Parsing! K. Frank |
From: Greg C. <gch...@sb...> - 2011-03-24 17:22:13
|
On 2011-03-24 16:16Z, K. Frank wrote: > > http://groups.google.com/group/comp.lang.c++/browse_thread/thread/c52862ddde8daaf6# Thanks. It has already been answered there. I was staring at those inserters in the standard, and I should have seen the answer... 27.6.1.2.2 basic_ostream<charT,traits>& operator<<(const void* p); 27.6.2.1 template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*); ...which is that the free function can't bind to a non-const reference. But those functions are the same in C++2003, AFAICT, so is 'g++ -std=c++0x' in error? |
From: K. F. <kfr...@gm...> - 2011-03-26 02:17:20
|
Hello Greg! A quick follow-up question... On Tue, Mar 22, 2011 at 9:53 AM, Greg Chicares <gch...@sb...> wrote: > On 2011-03-22 02:55Z, K. Frank wrote: >> >> Specifically, the following expression doesn't evaluate as I expect. >> >> dynamic_cast<std::stringstream&>(std::stringstream() << "xyz").str() > > I see a similar outcome running your testcase with Comeau C/C++ 4.3.10.1 > and MinGW gcc-3.4.5 . > >> It appears as if "xyz" is getting inserted into the temporary stringstream >> as a pointer rather than as a character string. > ... > Here's one more example that can be dropped into your testcase: > > std::string s("uvw"); > std::string s3b = dynamic_cast<std::stringstream&>(std::stringstream() << s).str(); > std::cout << "expecting uvw: " << s3b << std::endl; > > That succeeds with Comeau (but prints the pointer address), but fails > with MinGW gcc-3.4.5: > no match for 'operator<<' in 'stringstream(std::operator|( _S_out, _S_in)) << s' > and 'stringstream(std::operator|( _S_out, _S_in))'... I was playing around with this test case (inserting a std::string), because, according to my current understanding, it should fail to compile, as it does with mingw. I tried it with the Comeau online compiler (It doesn't actually build the final executable, so you can't run it.), and it fails to compile with an error analogous to that reported by mingw: "ComeauTest.c", line 27: error: no operator "<<" matches these operands operand types are: std::stringstream << std::string std::string s7 = dynamic_cast<std::stringstream&>(std::stringstream() << s).str(); (The online compiler announces itself as "Comeau C/C++ 4.3.10.1".) That is, I'm failing to reproduce with the online compiler your Comeau result. Any thoughts? Thanks. K. Frank |
From: Greg C. <gch...@sb...> - 2011-03-23 12:10:15
|
On 2011-03-23 11:46Z, Kai Tietz wrote: > [snip earlier discussion] > > Well, AFAICS is the issue that standard c++ doesn't supports this. It > is a c++0x standard thing and works perfectly by using 4.6.0 > toolchain. It might work with 4.5.x too. I just don't have such a > toolchain right now at hand. But try to use here option -std=c++0x. Indeed it does work as expected with MinGW gcc-4.5.0 and '-std=c++0x'. Can you say which section of the standard would change this behavior? I don't find the explanation by comparing 27.6.2.5.4 between the 1998 and 2003 editions. |
From: K. F. <kfr...@gm...> - 2011-03-23 14:53:15
|
Hi Kai and Greg! On Wed, Mar 23, 2011 at 8:10 AM, Greg Chicares <gch...@sb...> wrote: > On 2011-03-23 11:46Z, Kai Tietz wrote: >> > [snip earlier discussion] >> >> Well, AFAICS is the issue that standard c++ doesn't supports this. It >> is a c++0x standard thing and works perfectly by using 4.6.0 >> toolchain. It might work with 4.5.x too. I just don't have such a >> toolchain right now at hand. But try to use here option -std=c++0x. Thanks for this, Kai. Yes, the "base case", dynamic_cast<std::stringstream&>(std::stringstream() << "xyz").str() works for me with g++ 4.5 and -std=c++0x (but doesn't work with g++ 4.4 and -std=c++0x). Could you give us a hint as to what, specifically, isn't supported by the (pre-c++0x) standard? I've been poking around in the draft standard (rather randomly), and looking at a couple of summaries of c++0x changes: http://www2.research.att.com/~bs/C++0xFAQ.html http://www.aristeia.com/C++0x/C++0xFeatureAvailability.htm and for the life of me, I don't see anything that looks relevant. (By the way, using g++ 4.5 with -std=c++0x also lets dynamic_cast<std::stringstream&>(std::stringstream() << std::string("xyz")).str() compile and print out the string, rather than a pointer.) > Indeed it does work as expected with MinGW gcc-4.5.0 and '-std=c++0x'. > Can you say which section of the standard would change this behavior? > I don't find the explanation by comparing 27.6.2.5.4 between the > 1998 and 2003 editions. Please, yes. I second Greg's request. If anyone knows what specific feature is at issue here, please offer enlightenment. The only thing I can think of is that this use of an unnamed temporary leads to undefined behavior. (I can hardly imagine the standard saying "if you use a named variable, print out the string, but if it's an unnamed temporary, print out the pointer value.") Another test: dynamic_cast<std::stringstream&>(std::stringstream() << 123 << "xyz").str() dynamic_cast<std::stringstream&>(std::stringstream() << "xyz" << 123).str() dynamic_cast<std::stringstream&>(std::stringstream() << "abc" << "xyz").str() print out "123xyz", <pointer>"123", and <pointer>"xyz", respectively (but work correctly, in that they print out the character strings rather than the pointers with g++ 4.5 and -std=c++0x). It's as if once operator<< gets a hold of the stringstream and returns an ostream& everything works as expected (consistent with Greg's use of skipws). Thanks again, folks. K. Frank |
From: Kai T. <kti...@go...> - 2011-03-23 15:13:35
|
2011/3/23 K. Frank <kfr...@gm...>: > Hi Kai and Greg! > > On Wed, Mar 23, 2011 at 8:10 AM, Greg Chicares <gch...@sb...> wrote: >> On 2011-03-23 11:46Z, Kai Tietz wrote: >>> >> [snip earlier discussion] >>> >>> Well, AFAICS is the issue that standard c++ doesn't supports this. It >>> is a c++0x standard thing and works perfectly by using 4.6.0 >>> toolchain. It might work with 4.5.x too. I just don't have such a >>> toolchain right now at hand. But try to use here option -std=c++0x. > > Thanks for this, Kai. Yes, the "base case", > > dynamic_cast<std::stringstream&>(std::stringstream() << "xyz").str() > > works for me with g++ 4.5 and -std=c++0x (but doesn't work with > g++ 4.4 and -std=c++0x). > > Could you give us a hint as to what, specifically, isn't supported > by the (pre-c++0x) standard? I've been poking around in the draft > standard (rather randomly), and looking at a couple of summaries > of c++0x changes: > > http://www2.research.att.com/~bs/C++0xFAQ.html > http://www.aristeia.com/C++0x/C++0xFeatureAvailability.htm > > and for the life of me, I don't see anything that looks relevant. > > (By the way, using g++ 4.5 with -std=c++0x also lets > dynamic_cast<std::stringstream&>(std::stringstream() << > std::string("xyz")).str() > compile and print out the string, rather than a pointer.) > >> Indeed it does work as expected with MinGW gcc-4.5.0 and '-std=c++0x'. >> Can you say which section of the standard would change this behavior? >> I don't find the explanation by comparing 27.6.2.5.4 between the >> 1998 and 2003 editions. > > Please, yes. I second Greg's request. If anyone knows what specific > feature is at issue here, please offer enlightenment. > > The only thing I can think of is that this use of an unnamed temporary > leads to undefined behavior. (I can hardly imagine the standard > saying "if you use a named variable, print out the string, but if it's > an unnamed temporary, print out the pointer value.") > > Another test: > > dynamic_cast<std::stringstream&>(std::stringstream() << 123 << "xyz").str() > dynamic_cast<std::stringstream&>(std::stringstream() << "xyz" << 123).str() > dynamic_cast<std::stringstream&>(std::stringstream() << "abc" << "xyz").str() > > print out "123xyz", <pointer>"123", and <pointer>"xyz", respectively > (but work correctly, in that they print out the character strings rather > than the pointers with g++ 4.5 and -std=c++0x). > > It's as if once operator<< gets a hold of the stringstream and returns > an ostream& everything works as expected (consistent with Greg's > use of skipws). > > Thanks again, folks. > > > K. Frank > > ------------------------------------------------------------------------------ > Enable your software for Intel(R) Active Management Technology to meet the > growing manageability and security demands of your customers. Businesses > are taking advantage of Intel(R) vPro (TM) technology - will your software > be a part of the solution? Download the Intel(R) Manageability Checker > today! http://p.sf.net/sfu/intel-dev2devmar > _______________________________________________ > MinGW-users mailing list > Min...@li... > > This list observes the Etiquette found at > http://www.mingw.org/Mailing_Lists. > We ask that you be polite and do the same. Disregard for the list etiquette may cause your account to be moderated. > > _______________________________________________ > You may change your MinGW Account Options or unsubscribe at: > https://lists.sourceforge.net/lists/listinfo/mingw-users > Also: mailto:min...@li...?subject=unsubscribe > Hi, well I am not a real c++0x expert. But what I think the relevant difference in c++0x is to be found in paragraph 12.2 "Temporary objects" and its description about lifetime of temporaries. Regards, Kai |
From: Greg C. <gch...@sb...> - 2011-03-24 17:44:10
|
On 2011-03-24 17:22Z, Greg Chicares wrote: > > But those functions are the same in C++2003, AFAICT, However, C++0x extends beyond C++2003. > so is 'g++ -std=c++0x' in error? Or does N1377 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm come into play here? |
From: K. F. <kfr...@gm...> - 2011-03-24 18:16:17
|
Hi Greg! On Thu, Mar 24, 2011 at 1:22 PM, Greg Chicares <gch...@sb...> wrote: > On 2011-03-24 16:16Z, K. Frank wrote: >> >> http://groups.google.com/group/comp.lang.c++/browse_thread/thread/c52862ddde8daaf6# > > Thanks. It has already been answered there. I was staring at those > inserters in the standard, and I should have seen the answer... > > 27.6.1.2.2 > basic_ostream<charT,traits>& operator<<(const void* p); > 27.6.2.1 > template<class charT, class traits> > basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*); > > ...which is that the free function can't bind to a non-const reference. Yes, as far as the specific question I posted on comp.lang.c++, it looks like this is the solid, standard-based answer. On Thu, Mar 24, 2011 at 1:44 PM, Greg Chicares <gch...@sb...> wrote: > On 2011-03-24 17:22Z, Greg Chicares wrote: >> >> But those functions are the same in C++2003, AFAICT, I expect that g++ is largely compliant with c++2003, the current standard. > However, C++0x extends beyond C++2003. > >> so is 'g++ -std=c++0x' in error? Yes, "-std=c++0x" turns on some (a lot) of the features of the of the new c++0x draft standard. I agree that operator<< for char* is a free function in c++0x, that is, not a member function of ostream. (I have a copy of the draft standard, but unfortunately not a copy of the current standard, so I have to rely on others for what the current standard says.) So in terms of member / non-member function, we still have the same issue. But "-std=c++0x" might be right for another reason. > Or does N1377 > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm > come into play here? Yes, maybe. I think this is similar to what Kai was saying. I haven't yet absorbed 12.2, "Temporary objects," the section Kai referred to. (How shall I say this? I don't always find the language of the standard to be, well, optimally transparent.), I'm not sure that this is directly related to move semantics, but I think Kai is saying that the draft c++0x standard relaxes the restriction that prevents binding a non-const reference to a temporary. If so, then we can use the non-member operator<< for char* (by binding to its ostream& reference argument), rather than the member operator<< for void*. That would seem to give a consistent explanation of what we're seeing, and g++ would be correct in both cases (both with and without "-std=c++0x"). However, I don't think this explains the full breadth of what we are seeing (the skipws and other variations). (I didn't ask about those on comp.lang.c++.) I think I will let the comp.lang.c++ thread "season" a little bit while I try to understand the section 12.2 language about temporary variables. Then maybe I'll try to get my ducks in a row, and post some follow-up questions to the usenet thread. Thanks again for your thoughts. K. Frank |
From: Greg C. <gch...@sb...> - 2011-03-26 11:33:29
|
On 2011-03-26 02:17Z, K. Frank wrote: > > On Tue, Mar 22, 2011 at 9:53 AM, Greg Chicares <gch...@sb...> wrote: >> >> std::string s("uvw"); >> std::string s3b = dynamic_cast<std::stringstream&>(std::stringstream() << s).str(); >> std::cout << "expecting uvw: " << s3b << std::endl; >> >> That succeeds with Comeau (but prints the pointer address), but fails >> with MinGW gcc-3.4.5: >> no match for 'operator<<' in 'stringstream(std::operator|( _S_out, _S_in)) << s' >> and 'stringstream(std::operator|( _S_out, _S_in))'... > > I was playing around with this test case (inserting a std::string), > because, according to my current understanding, it should fail > to compile, as it does with mingw. Yes, I think so, too. The candidate (C++2003 21.3.7.9/4) is: template<class charT, class traits, class Allocator> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const basic_string<charT,traits,Allocator>& str); which is a free function in <string>. Its first argument is a non-const reference, which can't be bound to a temporary. > I tried it with the Comeau online compiler (It doesn't actually > build the final executable, so you can't run it.), and it fails to > compile with an error analogous to that reported by mingw: > > "ComeauTest.c", line 27: error: no operator "<<" matches these operands > operand types are: std::stringstream << std::string > std::string s7 = > dynamic_cast<std::stringstream&>(std::stringstream() << s).str(); > > (The online compiler announces itself as "Comeau C/C++ 4.3.10.1".) > > That is, I'm failing to reproduce with the online compiler your > Comeau result. Any thoughts? Abbreviated testcase: #include <iostream> #include <ostream> #include <sstream> #include <string> int main() { std::string s("uvw"); std::string s3b = dynamic_cast<std::stringstream&> ((std::stringstream()) << s).str(); std::cout << "expecting uvw: " << s3b << std::endl; } It compiles and links here: /home/Arktos/tmp[0]$export COMO_MIN_INCLUDE=/opt/lmi/como/mingw_for_como/include /home/Arktos/tmp[0]$PATH=/opt/lmi/como/bin:/opt/lmi/como/mingw_for_como/bin:/usr /bin:/bin:/usr/sbin:/sbin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygd rive/c/WINDOWS/System32/Wbem /home/Arktos/tmp[0]$como stringstream_cast_como.cpp Comeau C/C++ 4.3.10.1 (May 7 2008 09:22:38) for MS_WINDOWS_x86_Beta1 Copyright 1988-2008 Comeau Computing. All rights reserved. MODE:non-strict warnings MinGW C++ noC++0x_extensions and prints: /home/Arktos/tmp[0]$./aout expecting uvw: uvw However, pasting it here: http://www.comeaucomputing.com/tryitout/ I cannot find any combination of options that prevents the error we expect. The compilers aren't quite identical: Comeau C/C++ 4.3.10.1 (May 7 2008 09:22:38) [my local copy] Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) [online] but it's hard to believe that different builds of the same version of an EDG compiler would change this fundamental behavior. Wait...even with "Compile in relaxed mode", the online compiler gives an error; but if I add '--a' for strict mode locally, then I do get the expected error: /home/Arktos/tmp[0]$como --no_microsoft_bugs --a stringstream_cast_como.cpp Comeau C/C++ 4.3.10.1 (May 7 2008 09:22:38) for MS_WINDOWS_x86_Beta1 Copyright 1988-2008 Comeau Computing. All rights reserved. MODE:strict warnings [MinGW] C++ noC++0x_extensions "stringstream_cast_como.cpp", line 10: error: no operator "<<" matches these operands operand types are: std::stringstream << std::string ((std::stringstream()) << s).str(); ^ I don't normally use strict mode because it's incompatible with <windows.h>, but it's appropriate for this testcase. |
From: K. F. <kfr...@gm...> - 2011-03-26 12:32:50
|
Hi Greg! On Sat, Mar 26, 2011 at 7:33 AM, Greg Chicares <gch...@sb...> wrote: > On 2011-03-26 02:17Z, K. Frank wrote: >> >> On Tue, Mar 22, 2011 at 9:53 AM, Greg Chicares <gch...@sb...> wrote: >>> >>> std::string s("uvw"); >>> std::string s3b = dynamic_cast<std::stringstream&>(std::stringstream() << s).str(); >>> std::cout << "expecting uvw: " << s3b << std::endl; >>> >>> That succeeds with Comeau (but prints the pointer address), but fails >>> with MinGW gcc-3.4.5: >>> no match for 'operator<<' in 'stringstream(std::operator|( _S_out, _S_in)) << s' >>> and 'stringstream(std::operator|( _S_out, _S_in))'... >> ... >> I tried it with the Comeau online compiler (It doesn't actually >> build the final executable, so you can't run it.), and it fails to >> compile with an error analogous to that reported by mingw: >> >> "ComeauTest.c", line 27: error: no operator "<<" matches these operands >> operand types are: std::stringstream << std::string >> std::string s7 = >> dynamic_cast<std::stringstream&>(std::stringstream() << s).str(); >> >> (The online compiler announces itself as "Comeau C/C++ 4.3.10.1".) >> >> That is, I'm failing to reproduce with the online compiler your >> Comeau result. Any thoughts? > > Abbreviated testcase: > ... > It compiles and links here: > /home/Arktos/tmp[0]$export COMO_MIN_INCLUDE=/opt/lmi/como/mingw_for_como/include > /home/Arktos/tmp[0]$PATH=/opt/lmi/como/bin:/opt/lmi/como/mingw_for_como/bin:/usr > /bin:/bin:/usr/sbin:/sbin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygd > rive/c/WINDOWS/System32/Wbem > /home/Arktos/tmp[0]$como stringstream_cast_como.cpp > Comeau C/C++ 4.3.10.1 (May 7 2008 09:22:38) for MS_WINDOWS_x86_Beta1 > Copyright 1988-2008 Comeau Computing. All rights reserved. > MODE:non-strict warnings MinGW C++ noC++0x_extensions > and prints: > /home/Arktos/tmp[0]$./aout > expecting uvw: uvw > > However, pasting it here: > http://www.comeaucomputing.com/tryitout/ > I cannot find any combination of options that prevents the > error we expect. The compilers aren't quite identical: > Comeau C/C++ 4.3.10.1 (May 7 2008 09:22:38) [my local copy] > Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) [online] > but it's hard to believe that different builds of the same version > of an EDG compiler would change this fundamental behavior. > > Wait...even with "Compile in relaxed mode", the online compiler > gives an error; but if I add '--a' for strict mode locally, then > I do get the expected error: > /home/Arktos/tmp[0]$como --no_microsoft_bugs --a stringstream_cast_como.cpp > Comeau C/C++ 4.3.10.1 (May 7 2008 09:22:38) for MS_WINDOWS_x86_Beta1 > Copyright 1988-2008 Comeau Computing. All rights reserved. > MODE:strict warnings [MinGW] C++ noC++0x_extensions > > "stringstream_cast_como.cpp", line 10: error: no operator "<<" matches these > operands > operand types are: std::stringstream << std::string > ((std::stringstream()) << s).str(); > ^ > I don't normally use strict mode because it's incompatible with > <windows.h>, but it's appropriate for this testcase. Well, that's it bit odd.. But in any event, it sounds like Comeau recognizes the issue as you determined using strict mode. There is apparently some minor difference in Comea's strict / relaxed processing between your copy and the online version. No big deal, but thanks for checking. Best. K. Frank |
From: K. F. <kfr...@gm...> - 2011-03-29 15:26:00
|
Hello All! Just a quick follow-up: On Sat, Mar 26, 2011 at 8:32 AM, K. Frank wrote: > Hi Greg! > On Sat, Mar 26, 2011 at 7:33 AM, Greg Chicares <gch...@sb...> wrote: >> ... On 2011-03-22 02:55Z, K. Frank wrote: > Specifically, the following expression doesn't evaluate as I expect. > > dynamic_cast<std::stringstream&>(std::stringstream() << "xyz").str() > ... On Thu, Mar 24, 2011 at 12:16 PM, K. Frank wrote: > Hello Language Lawyers! > I posted this question about the stringstream temporary > to the usenet group comp.lang.c++. You can find it, for > example, here: > > http://groups.google.com/group/comp.lang.c++/browse_thread/thread/c52862ddde8daaf6# > ... The usenet thread on this question has pretty much run its course, and the folks over there have given quite a thorough and solid explanation of what's going on. You can find the gory details at the above-quoted link, but I thought I'd mention one point that was explained in the comp.lang.c++ thread: The reason the base-case code (quoted above) works with -std=c++0x is not that the new standard relaxes the restriction on (lvalue) references binding to temporaries (it doesn't), but rather that operator<< make use of the new c++0x rvalue references to make the above code work as desired. Section 27.7.2.9 ("Rvalue stream insertion," [ostream.rvalue]) adds the free-function: operator<<(basic_ostream<charT, traits>&& os, const T& x) The rvalue-reference argument os does bind to the temporary stringstream, and all is well. Thanks for everyone's help looking into this. K. Frank |
From: Kai T. <kti...@go...> - 2011-03-29 15:38:40
|
2011/3/29 K. Frank <kfr...@gm...>: > Hello All! > > Just a quick follow-up: > > On Sat, Mar 26, 2011 at 8:32 AM, K. Frank wrote: >> Hi Greg! >> On Sat, Mar 26, 2011 at 7:33 AM, Greg Chicares <gch...@sb...> wrote: >>> ... > > On 2011-03-22 02:55Z, K. Frank wrote: >> Specifically, the following expression doesn't evaluate as I expect. >> >> dynamic_cast<std::stringstream&>(std::stringstream() << "xyz").str() >> ... > > On Thu, Mar 24, 2011 at 12:16 PM, K. Frank wrote: >> Hello Language Lawyers! >> I posted this question about the stringstream temporary >> to the usenet group comp.lang.c++. You can find it, for >> example, here: >> >> http://groups.google.com/group/comp.lang.c++/browse_thread/thread/c52862ddde8daaf6# >> ... > > The usenet thread on this question has pretty much run its course, and > the folks over there have given quite a thorough and solid explanation of > what's going on. > > You can find the gory details at the above-quoted link, but I thought I'd > mention one point that was explained in the comp.lang.c++ thread: > > The reason the base-case code (quoted above) works with -std=c++0x > is not that the new standard relaxes the restriction on (lvalue) references > binding to temporaries (it doesn't), but rather that operator<< make use of > the new c++0x rvalue references to make the above code work as desired. > > Section 27.7.2.9 ("Rvalue stream insertion," [ostream.rvalue]) adds the > free-function: > > operator<<(basic_ostream<charT, traits>&& os, const T& x) > > The rvalue-reference argument os does bind to the temporary stringstream, > and all is well. > > > Thanks for everyone's help looking into this. > > > K. Frank Thanks, for pointing it out. Kai |