[type_index] Interest in dynamic_cast emulation?
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
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.
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?
On Thu, 14 Jul 2016 at 19:03 Gavin Lambert
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
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. -- View this message in context: http://boost.2283326.n4.nabble.com/type-index-Interest-in-dynamic-cast-emula... Sent from the Boost - Dev mailing list archive at Nabble.com.
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/ee7b15a493d10bc1fad93a12ab42f2f...
Usage:
1. #include
On 15 July 2016 at 23:53, 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/ee7b15a493d10bc1fad93a12ab42f2f...
Usage:
1. #include
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
(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
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
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=sharin... https://drive.google.com/file/d/0B81IxGu6wOjGdm02R0g2VmNGTE0/view?usp=sharin...* 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=sharin... https://drive.google.com/file/d/0B81IxGu6wOjGdnl5a3BSUEJRSHM/view?usp=sharin...* 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
participants (5)
-
Chris Glover
-
Gavin Lambert
-
Klaim - Joël Lamotte
-
Klemens Morgenstern
-
Marcel Raad