Prev: reasoning of ::std::cout (ostream) conversion w.r.t. plain, signed and unsigned chars...
Next: ANNOUNCE: just::thread library V1.3 released
From: Johannes Schaub (litb) on 17 Jan 2010 02:11 pfultz2 wrote: > When i use the curiously recurring template pattern, do i need to use > the reinterpret_cast to get the derived class or do i use the > static_cast? And is there a performance penalty in doing this cast? > For example > template<class Derived> > class Base > { > public: > void foo() > { > reinterpret_cast<Derived*>(this)->bar(); //or can i use a static > cast here? > } > }; > > class MyClass : Base<MyClass> > { > public: > void bar(); > }; > Im under the assumption that a static cast wouldnt work since the > derived class is not known at compile time. And if it werent then > would a reinterpret_cast be safe, if it were always used this way?? > In this example static_cast won't work. That's because the derivation is private. So only the derived class and its members/friends can access the inheritance, but not the base or another class. But using reinterpret_cast is wrong: The pointer result is not guaranteed to actually point to the derived class. If the result will point to something else, then you may run into undefined behavior when executing the member function. As a solution you can use a c style cast. C style casts will use a modified static_cast: The static_cast, when used by a C-style cast, will be able to access private inheritance. It will *not* use reinterpret_cast for the conversion. So using a c-style cast you will go fine. The only problem then is that your cast is unchecked: If "Derived" is not actually a derived class, the cast will use reinterpret_cast. And you won't notice. You can check this, though: template<typename Derived> struct Base { Derived *get_derived() { // ensure Derived is a (possibly not accessible) derived class. sizeof DERIVED_DOES_NOT_INHERIT(inheritance<Derived>()); return (Derived*)this; } private: char DERIVED_DOES_NOT_INHERIT(Base&); char DERIVED_DOES_NOT_INHERIT(Base*); template<typename D> struct inheritance : D { operator Base*(); // If D does *not* inherit Base, then // this one is possible for the first operator Base&(); }; }; If "Derived" does not inherit "Base", then this will cause an ambiguity. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Ulrich Eckhardt on 17 Jan 2010 21:47
peter koch larsen wrote: > What I don't understand is your comment to your own post. There is no > polymorphism and in the actual case dynamic_cast will not be > available. I'm not exactly sure what you mean either. What I said was that in order to use a 'dynamic_cast<derived*>' on a 'base*', 'base' must be polymorphic. It is not enough if 'derived' is polymorphic. Uli -- Sator Laser GmbH Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932 [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |