[type_index] Interest in dynamic_cast emulation?

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

[type_index] Interest in dynamic_cast emulation?

Chris Glover
Hi,

I reached for Boost.TypeIndex the other day expecting to find a kind of
dynamic_cast I could use in the absence of Rtti. I didn't find it, so I
wrote something to emulate it using type_index internally.

It's working, but before I go too far and clean this up and possibly submit
a pull request, I would like to gauge if there's interest in such a thing
or if there's some fundamental reason why it doesn't exist.

So, thoughts?

Thanks,

-- chris

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_index] Interest in dynamic_cast emulation?

Klemens Morgenstern

Am 14.07.2016 um 14:13 schrieb Chris Glover:

> Hi,
>
> I reached for Boost.TypeIndex the other day expecting to find a kind of
> dynamic_cast I could use in the absence of Rtti. I didn't find it, so I
> wrote something to emulate it using type_index internally.
>
> It's working, but before I go too far and clean this up and possibly submit
> a pull request, I would like to gauge if there's interest in such a thing
> or if there's some fundamental reason why it doesn't exist.
>
> So, thoughts?
>
> Thanks,
>
> -- chris
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Sounds useful to me. I would be interested in the implementation.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_index] Interest in dynamic_cast emulation?

Gavin Lambert
In reply to this post by Chris Glover
On 15/07/2016 00:13, Chris Glover wrote:
> I reached for Boost.TypeIndex the other day expecting to find a kind of
> dynamic_cast I could use in the absence of Rtti. I didn't find it, so I
> wrote something to emulate it using type_index internally.
>
> It's working, but before I go too far and clean this up and possibly submit
> a pull request, I would like to gauge if there's interest in such a thing
> or if there's some fundamental reason why it doesn't exist.

If you're writing the sort of program that needs dynamic_casts, I would
question why you have RTTI turned off in the first place.  The compiler
ought to be able to implement it more efficiently than a library can.

Also I'm curious whether there are limitations on your implementation.
Does it support casts to intermediate types (not just the actual type),
casts in multi-inheritance hierarchies, casts in virtual base
hierarchies, etc?



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_index] Interest in dynamic_cast emulation?

Chris Glover
On Thu, 14 Jul 2016 at 19:03 Gavin Lambert <[hidden email]> wrote:

>
> If you're writing the sort of program that needs dynamic_casts, I would
> question why you have RTTI turned off in the first place.  The compiler
> ought to be able to implement it more efficiently than a library can.
>

There are a couple of reasons for this. The first is that not all of our
platforms support RTTI. This typically isn't a problem because we don't
usually want to use RTTI on those platforms anyway, but there always end up
being work arounds, such as people moving virtual functions to a base class
in order to call it from one call site. Or adding things like bool IsFoo()
to the base class, etc.

The second is that we would prefer to opt in on a per hierarchy basis,
rather than turn it on globally. In my opinion, depending on dynamic_cast
is generally undesirable, but it can be useful to design you're hierarchies
assuming dynamic_cast is available, at least for that hierarchy.


> Also I'm curious whether there are limitations on your implementation.
> Does it support casts to intermediate types (not just the actual type),
> casts in multi-inheritance hierarchies, casts in virtual base
> hierarchies, etc?
>
>
I believe it works in all cases, but I'm not sure if my tests are
comprehensive. One limitation might be performance, which you eluded to
earlier, so I will write some tests for that as well.

Since there seems to be at least some interest, I'm going to clean this up
get to some eyes on it -- especially the tests.

Thanks,

-- chris

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_index] Interest in dynamic_cast emulation?

Marcel Raad
Chris Glover wrote
The second is that we would prefer to opt in on a per hierarchy basis,
rather than turn it on globally. In my opinion, depending on dynamic_cast
is generally undesirable, but it can be useful to design you're hierarchies
assuming dynamic_cast is available, at least for that hierarchy.
+1. I would be interested too for that reason.
Reply | Threaded
Open this post in threaded view
|

Re: [type_index] Interest in dynamic_cast emulation?

Chris Glover
Hi,

I have placed an initial implementation here:

https://github.com/cdglove/type_index/tree/runtime_cast

Here's the commit:

https://github.com/cdglove/type_index/commit/ee7b15a493d10bc1fad93a12ab42f2fdfd260810

Usage:

1. #include <boost/type_index/runtime_cast.hpp>
2. Add a macro to your classes to opt in;

struct base {
    BOOST_TYPE_INDEX_REGISTER_CLASS_RTTI
};

3. Derived classes need to list bases

struct multiple_derived : base1, base2 {
    BOOST_TYPE_INDEX_REGISTER_CLASS_RTTI_BASES(base1, base2)
};

4. use boost::type_index::runtime_cast the same as dynamic_cast,
(boost::type_index::runtime_pointer_cast like other boost::*pointer casts.).

Example:

using namespace boost::typeindex;
multiple_derived d;
base1* b1 = &d;
multiple_derived* d2 = runtime_pointer_cast<multiple_derived>(b1);
BOOST_TEST_NE(d2, (multiple_derived*)nullptr);
base2* b2 = runtime_pointer_cast<base2>(b1);
BOOST_TEST_NE(b2, (base2*)nullptr);

Some notes about the implementation:

1. I am using a variadic template. This could be removed if backwards
compatibility is desired.
2. The error messages could use some work.
3. I'm not sure if the tests are comprehensive, does anyone see anything
I've missed? I believe I have considered all combinations of multiple and
virtual inheritance that could mess this up.
4. It's possible this doesn't belong in the type_index library.
5. Initial performance tests put this about 5x slower than dynamic cast.
But those tests are trivial so I need to construct something more complex
to get an accurate measure of real world performance.

Any feedback is welcome.

Thanks,

-- chris

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_index] Interest in dynamic_cast emulation?

Klaim - Joël Lamotte
On 15 July 2016 at 23:53, Chris Glover <[hidden email]> wrote:

> Hi,
>
> I have placed an initial implementation here:
>
> https://github.com/cdglove/type_index/tree/runtime_cast
>
> Here's the commit:
>
>
> https://github.com/cdglove/type_index/commit/ee7b15a493d10bc1fad93a12ab42f2fdfd260810
>
> Usage:
>
> 1. #include <boost/type_index/runtime_cast.hpp>
> 2. Add a macro to your classes to opt in;
>
> struct base {
>     BOOST_TYPE_INDEX_REGISTER_CLASS_RTTI
> };
>
> 3. Derived classes need to list bases
>
> struct multiple_derived : base1, base2 {
>     BOOST_TYPE_INDEX_REGISTER_CLASS_RTTI_BASES(base1, base2)
> };
>
> 4. use boost::type_index::runtime_cast the same as dynamic_cast,
> (boost::type_index::runtime_pointer_cast like other boost::*pointer
> casts.).
>
> Example:
>
> using namespace boost::typeindex;
> multiple_derived d;
> base1* b1 = &d;
> multiple_derived* d2 = runtime_pointer_cast<multiple_derived>(b1);
> BOOST_TEST_NE(d2, (multiple_derived*)nullptr);
> base2* b2 = runtime_pointer_cast<base2>(b1);
> BOOST_TEST_NE(b2, (base2*)nullptr);
>
> Some notes about the implementation:
>
> 1. I am using a variadic template. This could be removed if backwards
> compatibility is desired.
> 2. The error messages could use some work.
> 3. I'm not sure if the tests are comprehensive, does anyone see anything
> I've missed? I believe I have considered all combinations of multiple and
> virtual inheritance that could mess this up.
> 4. It's possible this doesn't belong in the type_index library.
> 5. Initial performance tests put this about 5x slower than dynamic cast.
> But those tests are trivial so I need to construct something more complex
> to get an accurate measure of real world performance.
>
> Any feedback is welcome.
>


Interesting way to provide dynamic casting.
However, if there is a way for the macro to be somewhere else than inside
the classes, I would prefer that.

Joël Lamotte

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_index] Interest in dynamic_cast emulation?

Chris Glover
>
>
> Interesting way to provide dynamic casting.
> However, if there is a way for the macro to be somewhere else than inside
> the classes, I would prefer that.
>
> Joël Lamotte
>
>
I would prefer that as well, but I can't think of a way to do it. This
information is dynamic and therefore implies that it needs to be encoded
into each instance. I can't think of a way to achieve that in a
non-intrusive way.

-- chris

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_index] Interest in dynamic_cast emulation?

Chris Glover
Hi,

I've written a better benchmark for emulated dynamic_cast (runtime_cast) vs
built in dynamic_cast and the results are surprising.

In my initial naive test, the compiler was able to optimize because it knew
the concrete types, in this test, I've made sure the concrete types are
unknown by using factory functions implemented in another translation unit.
With this method it looks like runtime_cast is never slower than
dynamic_cast, and usually faster by some margin. The amount of difference
depends on the compiler.

The benchmark is available on github:

git clone --recursive https://github.com/cdglove/rtti-benchmark.git

From there, you should just be able to simply configure via cmake and build
(all of the relevant code, including the modified typeindex, is included).
The test could be more comprehensive, but so far I am convinced this is a
good solution. I've added a couple of charts from two of tests here (GCC
5.3 and MSVC 19.0).

*https://drive.google.com/file/d/0B81IxGu6wOjGdm02R0g2VmNGTE0/view?usp=sharing
<https://drive.google.com/file/d/0B81IxGu6wOjGdm02R0g2VmNGTE0/view?usp=sharing>*
This one is showing the cast distance (ie: how far from the most derived
class to the class we're trying to cast to) vs time to do the cast, for a
single inheritance chain only (ie: no branches in the tree).

*https://drive.google.com/file/d/0B81IxGu6wOjGdnl5a3BSUEJRSHM/view?usp=sharing
<https://drive.google.com/file/d/0B81IxGu6wOjGdnl5a3BSUEJRSHM/view?usp=sharing>*
This one is showing the cast distance vs time to do the cast, for a
multiple virtual inheritance chain. This one doesn't go as deep just
because of number of classes needed.

Feedback welcome.

-- chris

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost