Topic: static cast via virtual base classes


Author: technews@kangaroologic.com ("Jonathan Turkanis")
Date: Tue, 10 Feb 2004 20:20:01 +0000 (UTC)
Raw View
"Petar#M" <petar@scs.cs.nyu.edu> wrote in message
news:3e097faf.0402090850.441d2715@posting.google.com...
> Dear All,
>
> It appears that in the current C++ standard there is no way to
> statically
> cast a pointer to a virtual base class to a derived class. The only
> way
> to do it is using a dynamic cast and only of the virtual base class
> has
> virtual methods.

Yes, but even in the latter case, the cast may fail.

>
> This limitation appears (to me) to be a major flaw. First, one
should
> be
> allowed to cast to a dervied class if the type of the derived class
is
> known, because obviously the scenario is well-defined.

Pick any class D with a virtual base B, such that you would like to
static_cast from B* to D*. Given this information alone, a compiler
must be able to figure out what code to generate for

    D* d = static_cast<D*>(b);

where b has type B*.

I can now define a new class which derives non-virtually from D in two
different ways:

    struct D2 : D { /*  */ };

    struct E : D, D2 { /*  */ };

Each object of type E now has two distinct subobjects of type D, which
share a single subobject of type B. The pointer b in the code above
could point to an object of type E. Which subobject of type D should
the pointer d point to after the static_cast?

If we new the fully-derived type of the object to which b points, we
could determine whether the cast could succeed; this is what
dynamic_cast does, and it cannot happen until run time.

Maybe you know all this, and when you say 'if the type of the derived
class is known' you mean 'if the fully-derived type of the complete
object is known'. If so, under what circumstance are you willing to
consider the fully-derived type as known to the compiler?

Jonathan


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: a9804814@unet.univie.ac.at (Thomas Mang)
Date: Thu, 12 Feb 2004 04:29:19 +0000 (UTC)
Raw View

Petar#M schrieb:

> Dear All,
>
> It appears that in the current C++ standard there is no way to
> statically
> cast a pointer to a virtual base class to a derived class. The only
> way
> to do it is using a dynamic cast and only of the virtual base class
> has
> virtual methods.
>
> This limitation appears (to me) to be a major flaw.

Nice proposal, but how to implement it in practice?

Consider this hierarchy:

class base{virtual ~base(){} };
class der1 : virtual public base{};
class der2: virtual public base{};
class diamond : public der1, public der2{};


The layout for der1 could look like this:
----------
|   der1   |
----------
|   base   |
----------


The layout for der2 could look like this:
----------
|   der2   |
----------
|   base   |
----------

And the layout for diamond could look like this:
----------
|diamond|
----------
|   der2   |
----------
|   der1   |
----------
|   base   |
----------


Now say you want to cast from base to der2.
Depending wether the real object is a der2 or a diamond, the compiler has to
add different offsets to get the der2 -part.
If it is a der2, the compiler has to add sizeof(base), if it is a diamond,
the compiler has to add sizeof(base) + sizeof(der1).
The necessary information is only available during runtime, and the
dynamic_cast extracts it.
But static_cast works at compile time.


regards,

Thomas

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petar@scs.cs.nyu.edu (Petar#M)
Date: Fri, 13 Feb 2004 22:13:51 +0000 (UTC)
Raw View
Thank you all for responding.

First, as a clarification. I did mean to say that this static cast can
only be done when we know the type of the most derived class at compile
time. Looking at some of the examples you give, I imagine some people must
have been confused about it.

Second, even though the compiler doesn't support this operation, I came
up with a way to achieve it on my own. Here we go:

Let's say you wanted to have something like this:

class vbase {};
class mid1 : public virtual vbase {};
class mid2 : public virtual vbasa {};
class most : public mid1, public mid2 {};

and you want to be able to static cast "vbase *" to "most *".
Now, replace the code above with the following:

template<class SUP>
class subtype {
public:
  typedef SUP supertype;
  SUP *super () { return static_cast<SUP *> (this); }
  const SUP *super () const { return static_cast<const SUP *> (this); }
};

class vbase {};

template<class SUP>
class mid1 : public subtype2<SUP> {};

template<class SUP>
class mid2 : public subtype2<SUP> {};

class most : public vbase, public mid1<most>, public mid2<most> {};


Now, anywhere from within mid1 or mid2, you can call vbase's methods
by saying super ()->method_name (), e.g.

This technique is very powerful, and I've used it to achieve other
goals. At some point I'll put together a small survey of C++ tricks
on http://petar.info, which will look at the wider range of applications.

== Petar


technews@kangaroologic.com ("Jonathan Turkanis") wrote in message news:<c09pef$13r9bo$1@ID-216073.news.uni-berlin.de>...
> "Petar#M" <petar@scs.cs.nyu.edu> wrote in message
> news:3e097faf.0402090850.441d2715@posting.google.com...
> > Dear All,
> >
> > It appears that in the current C++ standard there is no way to
> > statically
> > cast a pointer to a virtual base class to a derived class. The only
> > way
> > to do it is using a dynamic cast and only of the virtual base class
> > has
> > virtual methods.
>
> Yes, but even in the latter case, the cast may fail.
>
> >
> > This limitation appears (to me) to be a major flaw. First, one
>  should
> > be
> > allowed to cast to a dervied class if the type of the derived class
>  is
> > known, because obviously the scenario is well-defined.
>
> Pick any class D with a virtual base B, such that you would like to
> static_cast from B* to D*. Given this information alone, a compiler
> must be able to figure out what code to generate for
>
>     D* d = static_cast<D*>(b);
>
> where b has type B*.
>
> I can now define a new class which derives non-virtually from D in two
> different ways:
>
>     struct D2 : D { /*  */ };
>
>     struct E : D, D2 { /*  */ };
>
> Each object of type E now has two distinct subobjects of type D, which
> share a single subobject of type B. The pointer b in the code above
> could point to an object of type E. Which subobject of type D should
> the pointer d point to after the static_cast?
>
> If we new the fully-derived type of the object to which b points, we
> could determine whether the cast could succeed; this is what
> dynamic_cast does, and it cannot happen until run time.
>
> Maybe you know all this, and when you say 'if the type of the derived
> class is known' you mean 'if the fully-derived type of the complete
> object is known'. If so, under what circumstance are you willing to
> consider the fully-derived type as known to the compiler?
>
> Jonathan
>
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petar@scs.cs.nyu.edu (Petar#M)
Date: Tue, 10 Feb 2004 04:07:25 +0000 (UTC)
Raw View
Dear All,

It appears that in the current C++ standard there is no way to
statically
cast a pointer to a virtual base class to a derived class. The only
way
to do it is using a dynamic cast and only of the virtual base class
has
virtual methods.

This limitation appears (to me) to be a major flaw. First, one should
be
allowed to cast to a dervied class if the type of the derived class is
known, because obviously the scenario is well-defined. Second, this
functionality is vital in certain very natural situations on which I
could give more detail provided my statements above are verified by
the readers of the list and there is
interest in the topic.

Best,
Petar

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Tue, 10 Feb 2004 18:24:14 +0000 (UTC)
Raw View
In article <3e097faf.0402090850.441d2715@posting.google.com>, Petar#M
<petar@scs.cs.nyu.edu> writes
>Dear All,
>
>It appears that in the current C++ standard there is no way to
>statically
>cast a pointer to a virtual base class to a derived class. The only
>way
>to do it is using a dynamic cast and only of the virtual base class
>has
>virtual methods.
>
>This limitation appears (to me) to be a major flaw. First, one should
>be
>allowed to cast to a dervied class if the type of the derived class is
>known, because obviously the scenario is well-defined. Second, this
>functionality is vital in certain very natural situations on which I
>could give more detail provided my statements above are verified by
>the readers of the list and there is
>interest in the topic.


Please could you give a source code example of what you mean because I
cannot see how it could possibly work with any measure of safety. It
seems to me that it would be about as vicious a downcast as you could
get.

--
Francis Glassborow      ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: wade@stoner.com (Bill Wade)
Date: Tue, 10 Feb 2004 18:24:19 +0000 (UTC)
Raw View
petar@scs.cs.nyu.edu (Petar#M) wrote in message news:<3e097faf.0402090850.441d2715@posting.google.com>...

> It appears that in the current C++ standard there is no way to
> statically
> cast a pointer to a virtual base class to a derived class. The only
> way
> to do it is using a dynamic cast and only of the virtual base class
> has
> virtual methods.
>
> This limitation appears (to me) to be a major flaw.

The restriction is there for good reasons.  If you know the actual
most-derived class you can get a significant speedup (>6x on VC7.1
release code for a simple diamond) over

  dynamic_cast<D*>(b_ptr)

with

  static_cast<D*>(static_cast<MOST_DERIVED*>(dynamic_cast<void*>(b_ptr)))

assuming the base class is polymorphic.  In the case where D is the
same as MOST_DERIVED you can get rid of one of the static casts.

This works faster because dyn_cast to void* is faster (on many
implementations) than arbitrary dyn_cast.

This works correctly if your compiler agrees that 5.2.7(7) means that
  dynamic_cast<void*>(b)
is a shorthand for
  static_cast<void*>(dynamic_cast<MOST_DERIVED*>(b))
(without some "public" worries).  I suppose other interpretations are
possible.
HTH, YMMV

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Richard_Damon@hotmail.com (Richard Damon)
Date: Tue, 10 Feb 2004 18:24:28 +0000 (UTC)
Raw View
petar@scs.cs.nyu.edu (Petar#M) wrote:

>Dear All,
>
>It appears that in the current C++ standard there is no way to
>statically
>cast a pointer to a virtual base class to a derived class. The only
>way
>to do it is using a dynamic cast and only of the virtual base class
>has
>virtual methods.
>
>This limitation appears (to me) to be a major flaw. First, one should
>be
>allowed to cast to a dervied class if the type of the derived class is
>known, because obviously the scenario is well-defined. Second, this
>functionality is vital in certain very natural situations on which I
>could give more detail provided my statements above are verified by
>the readers of the list and there is
>interest in the topic.
>
>Best,
>Petar

The issue is that the compiler does not know how to "statically" case the
pointer. Let us take the following case:

class VB {
};

class B1 : public virtual VB {
};

class B2 : public virtual VB {
};

class D : public B1, B2 {
};

Typical Object Layout

VB:
(VB data)

B1:
VB* vbdata
(B1 data)
<VB>
(VB data)

B2:
VB* vbdata
(B2 data)
<VB>
(VB data)

D:
<B1>
VB* vbdata
(B1 Data)
<B2>
VB* vbdata
(B2 data)
<VB>
(VB data)

we want to be able to statically cast a VB* to a B1*, but the compiler does not
know if the object being pointed to is really a B1 or a D. In typical
implementations both classes B1 and B2 will need to have a pointer to where VB
is because in general they can not know where the data is in respect to the base
of that (sub)object. VB can not have pointers to the classes using is as it does
not (and can not) know how many. To convert a VB* to a B1* we need to know if
the B1 is a B1 by itself or a B1 in a D (or something else). This knowledge is
not static information by dynamic, thus the need for a dynamic_cast.

--
richard_damon@iname.com (Redirector to my current best Mailbox)
rdamon@beltronicsInspection.com (Work Adddress)
Richad_Damon@msn.com (Just for Fun)

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]