Downcast taking account of virtual inheritance

Hi, I have a generic class that needs to downcast from a base class to a template class. The template class can use virtual inheritance or not. When the derived class use virtual inheritance I need to use dynamic cast, but not on the other cases. I'm wondering if a new downcast function that will take in account these facts would be of interest in Boost. clase B {...}; class D : public B {...}; class DV : public virtual B {...}; B* ptr; ptr= new D(); D* dPtr = downcast<D*>(ptr); // uses static_cast as is_virtual_base_of<B,D>::type is false ptr= new DV(); DV* dPtr = downcast<DV*>(ptr); // uses dynamic_cast as is_virtual_base_of<B,DV>::type is true What would be a good name for this downcast function? Best, _____________________ Vicente Juan Botet Escribá

Zitat von "vicente.botet" <vicente.botet@wanadoo.fr>:
B* ptr; ptr= new D(); D* dPtr = downcast<D*>(ptr); // uses static_cast as is_virtual_base_of<B,D>::type is false
ptr= new DV(); DV* dPtr = downcast<DV*>(ptr); // uses dynamic_cast as is_virtual_base_of<B,DV>::type is true
What would be a good name for this downcast function?
http://www.boost.org/doc/libs/1_42_0/libs/serialization/doc/smart_cast.html

----- Original Message ----- From: <strasser@uni-bremen.de> To: <boost@lists.boost.org> Sent: Sunday, February 14, 2010 6:35 PM Subject: Re: [boost] Downcast taking account of virtual inheritance
Zitat von "vicente.botet" <vicente.botet@wanadoo.fr>:
B* ptr; ptr= new D(); D* dPtr = downcast<D*>(ptr); // uses static_cast as is_virtual_base_of<B,D>::type is false
ptr= new DV(); DV* dPtr = downcast<DV*>(ptr); // uses dynamic_cast as is_virtual_base_of<B,DV>::type is true
What would be a good name for this downcast function?
http://www.boost.org/doc/libs/1_42_0/libs/serialization/doc/smart_cast.html
Thanks, I'll take a look on this. BTW, it would be a good idead to add a link from the conversion library page to this page. Is there any issue to do that? Vicente

As part of your efforts, you might want to checkout "smart_cast" which is a documented part of the serialization library. Robert Ramey

----- Original Message ----- From: "Robert Ramey" <ramey@rrsd.com> To: <boost@lists.boost.org> Sent: Sunday, February 14, 2010 6:47 PM Subject: Re: [boost] Downcast taking account of virtual inheritance
As part of your efforts, you might want to checkout "smart_cast" which is a documented part of the serialization library.
The idea correspond quite closely to my needs. I have used it in my code and it works. The implementation is based on whether the base type is polymorphic, not whether the base type is_virtual_base_of<B,D>. I have replaced template<class U> static T cast(U * u){ typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< BOOST_DEDUCED_TYPENAME mpl::and_< mpl::not_<is_base_and_derived< BOOST_DEDUCED_TYPENAME remove_pointer<T>::type, U > >, mpl::not_<is_base_and_derived< U, BOOST_DEDUCED_TYPENAME remove_pointer<T>::type > > >, mpl::identity<cross>, mpl::identity<linear> >::type typex; return typex::cast(u); } by template<class U> static T cast(U * u){ typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< is_virtual_base_of<U, BOOST_DEDUCED_TYPENAME remove_pointer<T>::type>, mpl::identity<cross>, mpl::identity<linear> >::type typex; return typex::cast(u); } And it work also. But now dynamic_cast is used only if U is virtual_base_of T. Can this be added to smart_cast? Thanks, Vicente

vicente.botet wrote:
And it work also. But now dynamic_cast is used only if U is virtual_base_of T. Can this be added to smart_cast?
And can it be made available outside of serialization ? -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

joel falcou wrote:
vicente.botet wrote:
And it work also. But now dynamic_cast is used only if U is virtual_base_of T. Can this be added to smart_cast?
And can it be made available outside of serialization ?
You can just include boost/serialization/smart_cast.hpp right now. Until about two years ago, you could have just included boost/smart_cast.hpp but, after 6 years of being there I got a huge amount of grief for putting it there and it was removed. If someone were interested, it could be enhanced to include any missing pieces and subjected to it's own review and then moved back into boost/ or boost/utility ... . I would be happy to see someone take ownership of it. Robert Ramey

Robert Ramey wrote:
You can just include boost/serialization/smart_cast.hpp right now. <snip>
I see. My main cocnern is that in a bcp use case, having bcp pulling all serialization for smart_cast is a bit of an overkill. I think it deserves to live its own life in utility

Joel Falcou wrote:
Robert Ramey wrote:
You can just include boost/serialization/smart_cast.hpp right now. <snip>
I see. My main cocnern is that in a bcp use case, having bcp pulling all serialization for smart_cast is a bit of an overkill. I think it deserves to live its own life in utility
So did I. And that's the way it was. But I was pressured by other boost developers to move to the private area of the serialization library as it had not be reviewed and accepted on it's own. This was in spite of the fact there were and are a large number of components in the "core" which have never been reviewed. In any case, if you feel this way, why don't re-package this as a separate library, add some tests, and submit it for a for a mini-review. I would then drop it from the serialization library. BTW - another component in exactly the same situation would be "state_saver", BOOST_STATIC_WARNING and perhaps others. Robert Ramey
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Feb 14, 2010, at 2:55 PM, vicente.botet wrote:
The implementation is based on whether the base type is polymorphic, not whether the base type is_virtual_base_of<B,D>. I have replaced
template<class U> static T cast(U * u){ typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< BOOST_DEDUCED_TYPENAME mpl::and_< mpl::not_<is_base_and_derived< BOOST_DEDUCED_TYPENAME remove_pointer<T>::type, U
, mpl::not_<is_base_and_derived< U, BOOST_DEDUCED_TYPENAME remove_pointer<T>::type
, mpl::identity<cross>, mpl::identity<linear> ::type typex; return typex::cast(u); } by template<class U> static T cast(U * u){ typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< is_virtual_base_of<U, BOOST_DEDUCED_TYPENAME remove_pointer<T>::type>, mpl::identity<cross>, mpl::identity<linear> ::type typex; return typex::cast(u); }
And it work also. But now dynamic_cast is used only if U is virtual_base_of T.
I don't think this change is correct, as it will result in using static_cast in an actual cross-cast situation, i.e. when there is no base/derived relationship between U and T, but they have a common derived type of which the value being cast is an instance. However, it seems to me that there is a bug in the existing smart_cast implementation, in that it may incorrectly attempt to use static_cast in the case where U is a virtual_base_of T. I think the correct fix is to leave the existing derivation test in place, but augment it with the is_virtual_base_of test, i.e. mpl::or_ the existing test for cross-cast (T and U have no base/derived relationship) with the is_virtual_base_of test.

Kim Barrett wrote:
However, it seems to me that there is a bug in the existing smart_cast implementation, in that it may incorrectly attempt to use static_cast in the case where U is a virtual_base_of T.
smart_cast predates the existence of is_virtual_base_of by about 9 years so I would expect this to be true.
I think the correct fix is to leave the existing derivation test in place, but augment it with the is_virtual_base_of test, i.e. mpl::or_ the existing test for cross-cast (T and U have no base/derived relationship) with the is_virtual_base_of test.
That would sound correct to me. Robert Ramey

----- Original Message ----- From: "Robert Ramey" <ramey@rrsd.com> To: <boost@lists.boost.org> Sent: Sunday, February 14, 2010 11:28 PM Subject: Re: [boost] Downcast taking account of virtual inheritance
Kim Barrett wrote:
I think the correct fix is to leave the existing derivation test in place, but augment it with the is_virtual_base_of test, i.e. mpl::or_ the existing test for cross-cast (T and U have no base/derived relationship) with the is_virtual_base_of test.
That would sound correct to me.
I have teste this and this should complete conveniently the smart_cast function. typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< BOOST_DEDUCED_TYPENAME mpl::or_< is_virtual_base_of<U, BOOST_DEDUCED_TYPENAME remove_pointer<T>::type, BOOST_DEDUCED_TYPENAME mpl::and_< mpl::not_<is_base_and_derived< BOOST_DEDUCED_TYPENAME remove_pointer<T>::type, U > >, mpl::not_<is_base_and_derived< U, BOOST_DEDUCED_TYPENAME remove_pointer<T>::type > > > >, // borland chokes w/o full qualification here mpl::identity<cross>, mpl::identity<linear> >::type typex; return typex::cast(u); Robert, could you add this enhancement for the next release. Thanks, Vicente
participants (6)
-
joel falcou
-
Joel Falcou
-
Kim Barrett
-
Robert Ramey
-
strasser@uni-bremen.de
-
vicente.botet