473,653 Members | 3,015 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Using temporary std::stream object

Hello,

In main(), the first output API is what I try to achieve. Unfortunately
it fails, printing first string as pointer instead of human readable
message. Tried to initialize str(""), set new buffer etc, but nothing
worked.

Ideas? Also might use another internal construct, only API is needed
and requirement to reuse existing std::ostream inserters.

App itself:
#include <iostream>
#include <sstream>
class printer
{
public:

void print (const std::string &s) {
std::cout << s << std::endl;
}
};
class stream: public std::ostringstr eam
{
public:

stream (printer &p): std::ostringstr eam(), printer_(p) {
// gets stored correctly
*this << "*** ";
}

~stream () {
printer_.print( str());
}

std::ostream &
operator* () {
return *this;
}
private:

printer &printer_;
};
int
main ()
{
printer p;

// want to achieve this but:
// prints address of string instead of "first"
stream(p) << "first" << " fails";

// works because first inserted object is not printed
stream(p) << std::flush << "ok 1";

// works because stream object is used through 'operator*'
// can be any other method returning this or *this
*stream(p) << "ok 2";

return 0;
}

May 19 '06 #1
3 3026
I've found some solutions, but my understanding of what is happening
is limited. As I see it, g++ won't consider the temporary stream
objects as viable arguments to functions taking 'stream&', just
'stream' or 'const stream&'. Thus the only insertion operators
considered are the member insertion operators (since the binary
variety all take non-const refs). Why are the member insertion
operators valid? I don't know. As a result,
'ostream::opera tor<<(void const*)' gets picked as the function used in
'stream(p) << "first"'.

You don't have this issue in other uses of '<<'.
'ostream::opera tor<<(void const*)' returns an ostream&, so
'operator<<(ost ream&, const char *)' gets called for ' << " fails"'.
Similarly, '*stream(p) << "ok 2"' works because 'stream::operat or*()'
returns an ostream&. '*this << "*** "' works because '*this' is a
'stream&'. &c.

What to do? I tried a couple alterations of your current
implementation. They all started with the idea of adding an
operator<< and most ended with const abuse. The simplest was to never
use a temporary 'stream', but this may not work for your application.

The shortest was to add:

std::ostream& operator<<(cons t stream& streme, const char* str) {
return (* const_cast<stre am&>(streme)) << str;
}

I also tried:

std::ostream& operator<<(stre am streme, const char* str) {
return (*streme) << str;
}

but it required more code than the first example above, and messy code
at that. For example, inserting into a local 'stream' object would
create a temporary 'stream', both of which would print. I created a
method to cancel a 'stream', but it needed to be called on a 'const
stream&', so I used a mutable member of 'stream'... It was
conceptually hideous. If you are only going to use temporary streams,
it might work for you; in this case, the only other thing you need to
add is a copy constructor.

You may be able to find a way of writing a stream::operato r<<(const
char*). Everytime I tried, g++ would complain that, according to ISO
C++, 'stream::operat or<<(const char*)' and 'operator<<(ost ream&, const
char*)' were ambiguous. If 'stream' didn't inherit from
'ostringstream' , this would definitely work, but you'd have to define
the various '<<(stream&, ARG2)' and '<<(ARG)' methods.

I tried to think of a way to use a factory method (called
stream::make) rather than a constructor to create streams (such an
approash shouldn't abuse constness), but couldn't do it without
dynamically created objects. Throw in smart pointers and it would
work with minimal changes to the API (use stream::make rather than
stream::stream) , but seems heavy handed.

I hope something here will work or set you off in the direction of a
workable solution.
May 21 '06 #2
Messed with code myself also and went quite similar direction as you
did: create new stream inserter that will return std::ostream, on which
following inserters will continue to work :)

Resolved ambiguity by making inserter member operator, that calls
external inserter and returns result stream.

Final solution:
#include <iostream>
#include <sstream>
class printer
{
public:

void
print (const std::string &s) {
std::cout << s << std::endl;
}
};
class stream: public std::ostringstr eam
{
public:

stream (printer &p): printer_(p) {}
~stream () {
printer_.print( str());
}
template <typename T>
std::ostream &
operator<< (const T &t) {
return static_cast<std ::ostream &>(*this) << t;
}
private:

printer &printer_;
};

int
main ()
{
printer p;
stream(p) << "now" << " works " << "well";

return 0;
}

May 21 '06 #3
In message <rn************ *************** *****@4ax.com>, Kanenas
<kanenas_@t_com cast_d.t_net> writes
I've found some solutions, but my understanding of what is happening
is limited. As I see it, g++ won't consider the temporary stream
objects as viable arguments to functions taking 'stream&', just
'stream' or 'const stream&'.
It's not just g++. No conformant compiler will, because you'd be binding
a temporary to a non-const reference, which is forbidden. Thus the only insertion operators
considered are the member insertion operators (since the binary
variety all take non-const refs). Why are the member insertion
operators valid? I don't know.
Because calling a non-const member function of a temporary doesn't bind
it to a reference.
As a result,
'ostream::oper ator<<(void const*)' gets picked as the function used in
'stream(p) << "first"'.

You don't have this issue in other uses of '<<'.
'ostream::oper ator<<(void const*)' returns an ostream&, so
'operator<<(os tream&, const char *)' gets called for ' << " fails"'.
Similarly, '*stream(p) << "ok 2"' works because 'stream::operat or*()'
returns an ostream&. '*this << "*** "' works because '*this' is a
'stream&'. &c.

What to do? I tried a couple alterations of your current
implementation . They all started with the idea of adding an
operator<< and most ended with const abuse. The simplest was to never
use a temporary 'stream', but this may not work for your application.


How about giving your stream class a function (or operator()) that
returns a reference to itself?

Then you can call it using e.g.

stream(p)() << "hello";

--
Richard Herring
May 22 '06 #4

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

Similar topics

8
2933
by: pt | last post by:
Hallo, i wonder how it is going to be of this code below regarding of the return of temporary object. Prototypes: =========== bool Activation(TCHAR *c); std::basic_string<TCHAR> GetFile();
15
6311
by: Dave Rahardja | last post by:
Hi all, Although the following definition is legal: const int& i = 5; ....and that the lifetime of the temporary variable to which i refers is identical to i itself, why would anyone want to do this instead of a simple const int i = 5;
11
11040
by: Marco Wedekind | last post by:
Hello all, I have a strange compiler behaviour with this code: ---- Begin of code snippet ---- class Base { public: static unsigned int ClassId();
2
1539
by: xllx.relient.xllx | last post by:
Assuming compiler optimizations are set to off, specifically to not allow the compiler to elide the copy constructor, would the following hold true?: If you call a function with an user-defined object by value as it's first and only argument, and this object was created before the function call (named object), would the compiler call the copy constructor to create a temporary object and initialize this object with the formal argument...
4
1585
by: Jess | last post by:
Hello, If a function's signature is: T f(); and it returns its result (of type T) by value, then the result will be copied into a temporary place, as a temporary object. If it is a temporary object, then can I still call T's function "g" like the following?
5
1669
by: Dario Menendez | last post by:
Is it possible to throw a reference to a temporary object? Will the temporary object be copied one or more times? See following example: struct my_exception { my_exception(int i) : i_(i) {} my_exception& ref() {return *this;} int i_;
1
2539
by: subramanian100in | last post by:
Consider the following: int x; int y; int z; (x+y) = z; For this statement, I get the following error with g++ compiler: error: non-lvalue in assignment Suppose I have a class Test and x, y, z are objects of type Test.
3
2033
by: subramanian100in | last post by:
Consider the code fragment: vector<intcontainer; container.insert(container.begin(), 10); int& ref = *--container.end(); From this, it looks like we can apply prefix decrement operator to container.end() - ie 'prefix --' can be applied to the iterator type
4
1623
by: cxf | last post by:
class A{ public: A() { func(0); }; virtual void func(int data) { printf("A1 :%d\n",data); }
0
8283
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 synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8811
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. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8590
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
6160
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 instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4147
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 the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4291
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2707
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1914
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
2
1591
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 effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.