Subclassing to get << and >>

  • Thread starter Christopher Benson-Manica
  • Start date
C

Christopher Benson-Manica

Sorry for the lame title, but it's hard to condense what I'm about to
say... Here's my situation (my first real C++ situation, yay!).
Currently we have a MyTCPThread (don't let the name scare you, this
isn't OT) that has a socket member object that has methods Send() and
GetLine() for sending and receiving data. I want to subclass
MyTCPThread so I can use << and >> as wrappers for Send() and
GetLine() (Send() is my primary concern at the moment, FWIW). I could
probably come up with some hackneyed scheme to do this on my own, but
I'd really like some advice on how to do it well.

My initial newbie thoughts suggest something like

class
MyStreamBasedTCPThread : public MyTCPThread
{
protected:
std::eek:stringstream outbuf;
};

but the big problem I see with this is how to make << apply to outbuf
(which will get sent) and still keep all the cool overloaded <<
operators that ostringstreams already have. I'm really feeling lost
looking for a good way to do this. I'd be extremely grateful for any
guidance!
 
F

fifo

At said:
Sorry for the lame title, but it's hard to condense what I'm about to
say... Here's my situation (my first real C++ situation, yay!).
Currently we have a MyTCPThread (don't let the name scare you, this
isn't OT) that has a socket member object that has methods Send() and
GetLine() for sending and receiving data. I want to subclass
MyTCPThread so I can use << and >> as wrappers for Send() and
GetLine() (Send() is my primary concern at the moment, FWIW). I could
probably come up with some hackneyed scheme to do this on my own, but
I'd really like some advice on how to do it well.

My initial newbie thoughts suggest something like

class
MyStreamBasedTCPThread : public MyTCPThread
{
protected:
std::eek:stringstream outbuf;
};

but the big problem I see with this is how to make << apply to outbuf
(which will get sent) and still keep all the cool overloaded <<
operators that ostringstreams already have. I'm really feeling lost
looking for a good way to do this. I'd be extremely grateful for any
guidance!

Well I'm not sure I understand what you're trying to do, but would
something like the following do what you want?

#include <string>
#include <iostream>
#include <sstream>

class foo
{
public:
void send(const std::string& str)
{ std::cout << "Sending: " << str << '\n'; }
};

template <class T>
foo& operator<<(foo& s, const T& t)
{
std::eek:stringstream ss;
ss << t;
s.send(ss.str());
return s;
}

int main()
{
foo f;

f << "Hello!\n";
f << "2 + 2 = " << 2 + 2 << '\n';
}
 
R

Rolf Magnus

fifo said:
Well I'm not sure I understand what you're trying to do, but would
something like the following do what you want?

#include <string>
#include <iostream>
#include <sstream>

class foo
{
public:
void send(const std::string& str)
{ std::cout << "Sending: " << str << '\n'; }
};

template <class T>
foo& operator<<(foo& s, const T& t)
{
std::eek:stringstream ss;
ss << t;
s.send(ss.str());
return s;
}

int main()
{
foo f;

f << "Hello!\n";
f << "2 + 2 = " << 2 + 2 << '\n';

Change that into:

f << "2 + 2 = " << 2 + 2 << std::endl;

adn try to compile it again.
 
C

Chris Theis

Christopher Benson-Manica said:
Sorry for the lame title, but it's hard to condense what I'm about to
say... Here's my situation (my first real C++ situation, yay!).
Currently we have a MyTCPThread (don't let the name scare you, this
isn't OT) that has a socket member object that has methods Send() and
GetLine() for sending and receiving data. I want to subclass
MyTCPThread so I can use << and >> as wrappers for Send() and
GetLine() (Send() is my primary concern at the moment, FWIW). I could
probably come up with some hackneyed scheme to do this on my own, but
I'd really like some advice on how to do it well.

[SNIP]

IMHO you're walking on thin ice with this because if you supply << and >>
then the class user will want to use the stream inserters and extractors
exactly the way they are used to. As Rolf already showed with his remark
this might become a very tedious business starting with stream manipulators
(like std::endl). Probably the easiest way is to stay with Send & Getline()
methods.

Cheers
Chris
 
C

Christopher Benson-Manica

Chris Theis said:
IMHO you're walking on thin ice with this because if you supply << and >>
then the class user will want to use the stream inserters and extractors
exactly the way they are used to. As Rolf already showed with his remark
this might become a very tedious business starting with stream manipulators
(like std::endl). Probably the easiest way is to stay with Send & Getline()
methods.

That's a good point, but I disagree that Send() is easier - either we
continue using <ot>temporary character buffers</ot> or static char
arrays (without being 100% sure they are big enough) and worrying
about populating them. Both of those alternatives seem like hassles
to me, so I think << and >> would at least make *my* life easier...
 
J

Jorge Rivera

That's a good point, but I disagree that Send() is easier - either we
continue using <ot>temporary character buffers</ot> or static char
arrays (without being 100% sure they are big enough) and worrying
about populating them. Both of those alternatives seem like hassles
to me, so I think << and >> would at least make *my* life easier...

There are some references online on how to subclass
std::basic_streambuf, std::basic_ostream and std::basic_istream. By
doing this, you would end up with a nice tcp_ostream and tcp_istream
objects that would behave like the other standard stream types.
 
J

Jonathan Turkanis

Christopher Benson-Manica said:
Sorry for the lame title, but it's hard to condense what I'm about to
say... Here's my situation (my first real C++ situation, yay!).
Currently we have a MyTCPThread (don't let the name scare you, this
isn't OT) that has a socket member object that has methods Send() and
GetLine() for sending and receiving data. I want to subclass
MyTCPThread so I can use << and >> as wrappers for Send() and
GetLine() (Send() is my primary concern at the moment, FWIW). I could
probably come up with some hackneyed scheme to do this on my own, but
I'd really like some advice on how to do it well.

My initial newbie thoughts suggest something like

class
MyStreamBasedTCPThread : public MyTCPThread
{
protected:
std::eek:stringstream outbuf;
};

but the big problem I see with this is how to make << apply to outbuf
(which will get sent) and still keep all the cool overloaded <<
operators that ostringstreams already have. I'm really feeling lost
looking for a good way to do this. I'd be extremely grateful for any
guidance!

I have a library (submitted to boost) which would allow you easily to
create a standard stream or stream buffer for writing to the TCP
connection if the underlying connection, if your interface is rich
enough to allow you to define a wrapper something like this

struct tcp_connection {
// Constructors, etc.
int read(char*, int);
void write(char*, int);
};

where read and write have the obvious semantics.

You'd end up with something like this

typedef resource_stream<tcp_connection> tcp_stream;
tcp_stream tcp;
tcp.open(tcp_connection("www.microsoft.com", 80));
tcp << "DELETE http://www.microsoft.com/ HTTP/1.1\r\n"
<< "Host: www.microsoft.com\r\n"
<< "Connection:close\r\n\r\n";
tcp.flush();

Jonathan
 
J

Jorge Rivera

Jonathan said:
I have a library (submitted to boost) which would allow you easily to
create a standard stream or stream buffer for writing to the TCP
connection if the underlying connection, if your interface is rich
enough to allow you to define a wrapper something like this

struct tcp_connection {
// Constructors, etc.
int read(char*, int);
void write(char*, int);
};

where read and write have the obvious semantics.

You'd end up with something like this

typedef resource_stream<tcp_connection> tcp_stream;
tcp_stream tcp;
tcp.open(tcp_connection("www.microsoft.com", 80));
tcp << "DELETE http://www.microsoft.com/ HTTP/1.1\r\n"
<< "Host: www.microsoft.com\r\n"
<< "Connection:close\r\n\r\n";
tcp.flush();

Jonathan
Can I get it?
 
J

Jonathan Turkanis

Jorge Rivera said:
Jonathan Turkanis wrote:
Can I get it?

Sure! Thanks for your interest. The Boost files section is sometimes
difficult to get into, so I've put up a copy here:

http://www.xmission.com/~turkanis/iostreams/

Look for the documentation in the 'lib' subdirectory. The
functionality described above is described in the docs in the section
"5.6 Unfiltered Streams and Stream Buffers"

Please let me know what you think. If you run into any problems, I'll
try to fix them immediately.

Jonathan
 
C

Christopher Benson-Manica

Christopher Benson-Manica said:
class
MyStreamBasedTCPThread : public MyTCPThread
{
protected:
std::eek:stringstream outbuf;
};

Thanks for the replies to this, but with my new understanding I don't
think I can do what I want here. If anyone cares, the real situation
(which I didn't attempt to describe in my original post) is something
like

class MySocket
{
public:
...
Send();
GetLine();
};

class MyTCPThread : MyBaseThreadClass // implementation not relevant
{
public:
...
MySocket socket;
};

What I wanted to do (I now know) was to wrap MySocket such that I
could send and receive using << and >>. Unfortunately, MyTCPThread
depends heavily on the functionality of MySocket, such that I can't
simply add a MyCoolSocket to the class and have it work correctly, and
I'm not at liberty to change the implemenation of MyTCPThread at all.
Oh well.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,161
Messages
2,570,892
Members
47,431
Latest member
ElyseG3173

Latest Threads

Top