From: Johannes Schaub (litb) on
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
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! ]