RE: [Boost-Users] boost::polymorphic_upcast suggestion

Jean Llorca (yg-boost-users@gmane.org) wrote:
I would like to propose, in the spirit of Bjarne Stroustrup book, an upcast (where target inherits source). Upcasting is already directly supported by the language. Given classes Base and Derived, with the public inheritance implied by their names, then:
Derived d; Base * b=&d; Base & br = d; will work without any casting whatsoever. When the compiler compiles this code, it has the definitions of classes Base and Derived available, so all the work can be performed at compile time.
template <class Target, class Source> inline Target polymorphic_upcast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET) {
typedef unsigned int uint;
uint offset = reinterpret_cast<uint>( static_cast<Source*>( reinterpret_cast<Target>(1) ) ) - 1; Target res = reinterpret_cast<Target>( reinterpret_cast<uint>( x ) - offset );
assert( res == dynamic_cast<Target>(x) );
return res; } I don't understand this - how is casting a Target to an unsigned int going to help? Did you perhaps mean Target * in the above example, or have I missed something?
-- Jim

Jim, "Jim.Hyslop" <jim.hyslop@leitch.com> a écrit dans le message de news: F5DF799F740CD611802200034722783C73664E@pelican.mars.leitch.com...
Jean Llorca (yg-boost-users@gmane.org) wrote:
I would like to propose, in the spirit of Bjarne Stroustrup book, an upcast (where target inherits source). Upcasting is already directly supported by the language. Given classes Base
I don't understand this - how is casting a Target to an unsigned int going to help? Did you perhaps mean Target * in the above example, or have I missed something? Yes, target is a pointer type, while Source isn't. That's because of the intended usage of this function which is A* a =
Here upcasting means casting a base class to a derived class, I know it may seem strange, bust boost offers a downcast which does the static_cast the language does implicitly already (check <boost/cast.hpp>). Upcasting is usually achieved by two ways: using reinterpret_cast directly, which is hazardous sometimes because the pointer to the various base classes are not equal to the derived class when you use multiple inheritance. The other and only safe way used is to use dynamic_cast. The code I suggested propose a safe upcast without the constraints of dynamic_cast. polymorphic_upcast<A*>( x ); Jean.

On Thursday, June 27, 2002, at 06:38 AM, Jean Llorca wrote:
Here upcasting means casting a base class to a derived class, I know it may seem strange, bust boost offers a downcast which does the static_cast the language does implicitly already (check <boost/cast.hpp>).
I think you've got it backwards. Downcasting, in Boost at least, means casting a pointer to a base class part of an object to a pointer to a derived class part of the same object. The polymorphic_downcast is *not* doing a static_cast for a conversion the language already does implicitly. Could you give a specific complete example (a file that would compile, with all the declarations) of how one would use what you're proposing to help make this clearer? -- Darin

"Darin Adler" <darin@bentspoon.com> a écrit dans le message de news: B586F909-89D7-11D6-9349-0003935B80A2@bentspoon.com...
On Thursday, June 27, 2002, at 06:38 AM, Jean Llorca wrote:
Here upcasting means casting a base class to a derived class, I know it may seem strange, bust boost offers a downcast which does the static_cast the language does implicitly already (check <boost/cast.hpp>).
I think you've got it backwards. Downcasting, in Boost at least, means casting a pointer to a base class part of an object to a pointer to a derived class part of the same object. The polymorphic_downcast is *not* doing a static_cast for a conversion the language already does implicitly.
template <class Target, class Source> inline Target polymorphic_downcast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET) { assert( dynamic_cast<Target>(x) == x ); // detect logic error return static_cast<Target>(x); } Sorry about it, but it's here in the code. This is in the last version of the CVS. It does a static_cast. The compiler does static_cast implicitly in some cases. For instance a C++ compiler replaces the assert line with: assert( dynamic_cast<Target>(x) == static_cast<Target>(x) );
Could you give a specific complete example (a file that would compile, with all the declarations) of how one would use what you're proposing to help make this clearer?
I enclosed two files to this reply. Don't scream about chosen class names and stuff in the example ;) begin 666 test.cpp M+R\@=&5S="YC<' @.B!$969I;F5S('1H92!E;G1R>2!P;VEN="!F;W(@=&AE M(&-O;G-O;&4@87!P;&EC871I;VXN#0HO+PT*#0HC:6YC;'5D92 \;G%C87-T M+F@^#0H-"@T*8VQA<W,@075J#0I[#0IP=6)L:6,Z#0H@(" @=FER='5A;"!^ M075J*"D@>WT[#0H@(" @=FER='5A;"!V;VED('-T=69F*"D@>WT[#0H@(" @ M=FER='5A;"!V;VED('=H871E=F5R*"D@/3 [#0H@(" @=FER='5A;"!V;VED M('=H871E=F5R,2@I(#TP.PT*<')O=&5C=&5D.@T*(" @(&EN="!I.PT*(" @ M(&-H87(@<V9L<VX[#0I].PT*#0H-"@T*8VQA<W,@0G5J#0I[#0IP=6)L:6,Z M#0H@(" @=FER='5A;"!V;VED('=H871E=F5R*"D@/3 [#0H@(" @=FER='5A M;"!V;VED('=H871E=F5R,B@I(#TP.PT*(" @('9I<G1U86P@?D)U:B@I('M] M.PT*<')O=&5C=&5D.@T*(" @(&EN="!I.PT*?3L-"@T*8VQA<W,@0W5J(#H@ M<'5B;&EC($%U:BP@<'5B;&EC($)U:@T*>PT*<'5B;&EC.@T*(" @('9I<G1U M86P@=F]I9"!W:&%T979E<B@I('M].PT*(" @('9I<G1U86P@=F]I9"!W:&%T M979E<C$H*2![?3L-"B @("!V:7)T=6%L('9O:60@=VAA=&5V97(R*"D@>WT[ M#0H@(" @=FER='5A;"!^0W5J*"D@>WT[#0I].PT*#0H-"@T*:6YT(&UA:6XH M:6YT(&%R9V,L(&-H87(J(&%R9W9;72D-"GL-"B @("!#=6H@86)L83L-"B @ M("!#=6HJ('!A8FQA(#T@)F%B;&$[#0H@(" @0G5J*B!S:7-I(#T@8F]O<W0Z M.G!O;'EM;W)P:&EC7V1O=VYC87-T/$)U:BH^*"!P86)L82 I.PT*(" @( T* M(" @($-U:BH@;&%B;&$@/2!P;VQY;6]R<&AI8U]U<&-A<W0\0W5J*CXH('-I M<VD@*3L-"B @("!I9B@@*'9O:60J*7!A8FQA(#T]("AV;VED*BEL86)L82 I M#0H@(" @(" @(')E='5R;B P.PT*(" @(&5L<V4-"B @(" @(" @<F5T=7)N +("TQ.PT*?0T*#0H` ` end begin 666 nqcast.h M(VEF;F1E9B!.44-A<W1?2%]);F-L=61E9 T*(V1E9FEN92!.44-A<W1?2%]) M;F-L=61E9 T*#0HC(&EN8VQU9&4@/&)O;W-T+V-A<W0N:'!P/@T*(R!I;F-L M=61E(#QB;V]S="]C;VYF:6<N:'!P/@T*(R!I;F-L=61E(#QB;V]S="]T>7!E M+FAP<#X-"@T*(R!I9B!D969I;F5D*$)/3U-47TU35D,I("8F($)/3U-47TU3 M5D,@/#T@,3(P," O+R Q,C P(#T@5D,V#0HC("!D969I;F4@3E%?15A03$E# M251?1$5&055,5%]405)'150@+" Z.F)O;W-T.CIT>7!E/%1A<F=E=#XJ(#T@ M, T*(R!E;'-E#0HC("!D969I;F4@3E%?15A03$E#251?1$5&055,5%]405)' M150-"B,@96YD:68-"@T*#0HO*BH-"BH@06QL;W=S(&9A<W1E<B!U<&-A<W1I M;F<L(%1A<F=E="!M=7-T(&EN:&5R:70@9G)O;2!S;W5R8V4-"BH-"BH@0&%U M=&AO<B!*96%N#0HJ+PT*=&5M<&QA=&4@/&-L87-S(%1A<F=E="P@8VQA<W,@ M4V]U<F-E/@T*:6YL:6YE(%1A<F=E="!P;VQY;6]R<&AI8U]U<&-A<W0H4V]U M<F-E*B!X($Y17T584$Q)0TE47T1%1D%53%1?5$%21T54*0T*>PT*(" @('5N M<VEG;F5D(&EN="!O9F9S970@/2!R96EN=&5R<')E=%]C87-T/'5N<VEG;F5D M(&EN=#XH('-T871I8U]C87-T/%-O=7)C92H^*"!R96EN=&5R<')E=%]C87-T M/%1A<F=E=#XH,2D@*2 I("T@,3L-"B @("!487)G970@<F5S(#T@<F5I;G1E M<G!R971?8V%S=#Q487)G970^*"!R96EN=&5R<')E=%]C87-T/'5N<VEG;F5D M(&EN=#XH('@@*2 M(&]F9G-E=" I.PT*(" @( T*(" @(&%S<V5R="@@<F5S M(#T](&1Y;F%M:6-?8V%S=#Q487)G970^*'@I("D[#0H@(" @#0H@(" @<F5T M=7)N(')E<SL-"GT-"@T*#0HC96YD:68@+R\@(VEF;F1E9B!.44-A<W1?2%]) );F-L=61E9 T* ` end

Hi, I feel I have to jump on this one ;-) Jean, I think you have this one backwards I'm afraid, take your example (stripped down a bit)
-----Original Message----- From: news [mailto:news@main.gmane.org]On Behalf Of Jean Llorca Sent: 27 June 2002 15:31 To: boost-users@yahoogroups.com Subject: [Boost-Users] Re: boost::polymorphic_upcast suggestion
"Darin Adler" <darin@bentspoon.com> a écrit dans le message de news: B586F909-89D7-11D6-9349-0003935B80A2@bentspoon.com...
On Thursday, June 27, 2002, at 06:38 AM, Jean Llorca wrote:
Here upcasting means casting a base class to a derived class, I know it may seem strange, bust boost offers a downcast which does the static_cast the language does implicitly already (check <boost/cast.hpp>).
I think you've got it backwards. Downcasting, in Boost at least, means casting a pointer to a base class part of an object to a pointer to a derived class part of the same object. The polymorphic_downcast is *not* doing a static_cast for a conversion the language already does implicitly.
template <class Target, class Source> inline Target polymorphic_downcast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET) { assert( dynamic_cast<Target>(x) == x ); // detect logic error return static_cast<Target>(x); }
Sorry about it, but it's here in the code. This is in the last version of the CVS. It does a static_cast. The compiler does static_cast implicitly in some cases. For instance a C++ compiler replaces the assert line with: assert( dynamic_cast<Target>(x) == static_cast<Target>(x) );
Could you give a specific complete example (a file that would compile, with all the declarations) of how one would use what you're proposing to help make this clearer?
I enclosed two files to this reply. Don't scream about chosen class names and stuff in the example ;)
participants (4)
-
Darin Adler
-
Jean Llorca
-
Jim.Hyslop
-
Sam Partington