Connecting Tech Pros Worldwide Forums | Help | Site Map

Downcast with smart pointers?

alebcn75@gmail.com
Guest
 
Posts: n/a
#1: Jul 21 '07
Hello,

I'm having a design issue that I can't solve. I'm getting from a
network a stream of data, which is a http message (my program is
neither a client or server, it just catches messages over the network)

For this I have a class http_message with the usual methods (to access
header, fields, etc)
I also have two other classes, http_request and http_response, which
should be used depending on the type of message received. These two
classes derive from http_message, and contain some more helper
methods. They don't have any data (as it uses the data from the base
class)

And this is my problem. At some point I'd like to instantiate a
request or response data, but I don't know how to do it, as I'm using
smart pointers instead of plain pointers (the program uses several
threads, and these objects are accessed by many of them)

If I were using simple pointers, I'd do a dynamic_cast, but how is
this done with a smart pointer? (I'm using the CountedPtr available in
many places) I thought about using a copy constructor in the request
and response classes, taking a message as parameter, and initializing
the object from there, but that doesn't look very well, does it?

Any comment about how to proceed in this case? Any advice/example will
be greatly appreciated.

Thanks.

alebcn75@gmail.com
Guest
 
Posts: n/a
#2: Jul 22 '07

re: Downcast with smart pointers?


Hi,
Quote:
Quote:
Then inside this function, I'd need to instantiate the correct object.
But how to do it? I tried:
>
Quote:
SmartPtr<HttpResponseresp = msg;
>
Quote:
But of course doesn't work. If I were using normal pointers, then I'd
do dynamic_cast<HttpResponse*>(msg) and everything ok.
>
It doesn't work because there is no implicit conversion from
SmartPtr<HttpMsgto SmartPtr<HttpResponse>. One possible way to do it
is to create a derived class from the standard smart pointer (of
course, if you have control of the pointer implemetation, do it
directly on its implementation), and add
>
a member template function in the auto_ptr implementation, similar to
this
>
template <class NEW_T>
operator auto_ptr<NEW_T>
{
return auto_otr<NEW_T(dynamic_cast (NEW_T *(this->get ()));
>
}
Correct me if I wrong, but in that case I'd get two separate smart
pointers, wouldn't I? I'd prefer that both pointers share the
reference count, otherwise it could be very dangerous (if original
smart pointer's count reach zero, then pointer would be deleted)
Unless of course that I do a deep copy of the inner object, but that
wouldn't be performance wise..

This is what I've trying to do. I took the implementation from here,
which is simple enough and fits my purposes (at least it did before
getting here!)

http://www.josuttis.de/libbook/cont/countptr.hpp.html

And to add support for dynamic_cast I made some additions:

Added this friend function:

template<class U>
friend
CountedPtr<UDynamic_Cast(CountedPtr<T>& sp)
{
U* upcast = dynamic_cast<U*>(sp.ptr);

if (upcast)
return CountedPtr<U>(upcast, sp.count);
else
return CountedPtr<U>;
}

For this to work, I had to create a new constructor which not only
takes a pointer, but an already existing counter. This way, I avoid
what I mentioned you above.

Unfortunately, it doesn't work. I'm getting an error saying this
(using VC6)

none of the 7 overloads can convert parameter 1 from type 'const class
CountedPtr<class HttpMsg>'

Also, now I'm getting another surprise: If I have this method
void foo(const CountedPtr<HttpMsgmsg);

Then if I have an instance:
CountedPtr<HttpRequestreq(new HttpRequest);

Then I'd like to do this:
foo(req);

But it doesn't work either! Why is that? Shouldn't upcasting work?

Thanks again.

alebcn75@gmail.com
Guest
 
Posts: n/a
#3: Jul 22 '07

re: Downcast with smart pointers?


You can't change the type of an object. When you instantiate a HttpMsg, you
Quote:
can't change the type to a HttpRequest or HttpResponse after that.
>
You can make a 'factory', a function that parses a buffer and gives you
either a HttpRequest or a HttpResponse:
>
SmartPtr<HttpMsgcreateMessage(const std::string& buffer)
{
// ... parse buffer...
if (isRequest)
return SmartPtr<HttpMsg>(new HttpRequest(buffer));
else
return SmartPtr<HttpMsg>(new HttpResponse(buffer));
>
}
Yes, I'm doing this now to create the appropriate object. But my
problem is that I'm passing this to a method that takes either request
or responses, so its parameter is a HttpMsg. And now I'm having two
problems: neither upcasting nor downcasting seem to work!
Quote:
Quote:
In some situations, I'd like to pass some of these objects to a
function, so assuming I have a generic function (because it could
either accept a request or response):
>
Quote:
void foo(const SmartPtr<HttpMsg>& msg);
>
Quote:
Then inside this function, I'd need to instantiate the correct object.
But how to do it? I tried:
>
Quote:
SmartPtr<HttpResponseresp = msg;
>
Quote:
But of course doesn't work. If I were using normal pointers, then I'd
do dynamic_cast<HttpResponse*>(msg) and everything ok.
>
Get the raw pointer and do a dynamic_cast. Or use another smart pointer
like boost::shared_ptr (which is tr1::shared_ptr), that has a dynamic_cast
replacement: dynamic_pointer_cast<>.
Yes, unfortunately I'd like to make my own, for simplicity purposes,
and for space. Also, some environments I use don't have std library
available.
Quote:
Well, smart pointers transfer ownership. If your foo() function here
doesn't store the HttpMsg object, it could take a const reference instead:
>
void foo(const HttpMsg& msg);
That would be one option. I assume it is safe enough.. but my problem
is that these messages are passed from one side to another, including
different threads..

Thanks!

kwikius
Guest
 
Posts: n/a
#4: Jul 22 '07

re: Downcast with smart pointers?


On 22 Jul, 12:35, alebc...@gmail.com wrote:
Quote:
Yes, but for the moment, I'd feel happy if I made it work even for
single thread environments.
I would recommend you get hold of a library with std::tr1::shared_ptr
for your compiler. It will be in the next C++ standard.
I don't know however where you can get such a library.. Only info I
can find is:

http://www.amazon.com/Standard-Libra.../dp/0321412990

Point is that smart pointers are tricky to get right, so before
rolling your own see what the current solutions are. There is a long
history of smart pointers and no perfect solution and many many subtle
problems.

(Someone may want to hint very similar lib to std::tr1::shared_ptr . I
aint going to though ;-))

regards
Andy Little



Closed Thread