Why is RTTI necessary?
Asked Answered
c++
I

2

6

Why is RTTI (Runtime Type Information) necessary?

Isbella answered 16/4, 2010 at 3:24 Comment(0)
S
13

RTTI, Run-Time Type Information, introduces a [mild] form of reflection for C++.

It allows to know for example the type of a super class, hence allowing to handle an heterogeneous collection of objects which are all derived from the same base type. in ways that are specific to the individual super-classes. (Say you have an array of "Vehicle" objects and need to deal differently with the "Truck" objects found amid the array).

The question whether RTTI is necessary is however an open one. Story has it that Bjarne Stroustrup purposefully excluded this feature from the original C++ specification, by fear that it would be misused.
There are indeed opportunities to overuse/misuse reflection features, and this may have been even more of a factor when C++ was initially introduced because there wasn't such a OOP culture in the mainstream programmer community.
This said, with a more OOP savvy community, with the effective demonstration of all the good things reflection can do (eg. with languages such as Java or C#) and with the fancy design patterns in use nowadays, I strongly believe that RTTI and reflection features at large are very important even if sometimes misused.

Singsong answered 16/4, 2010 at 3:34 Comment(4)
Stroustrup's fears were justified. Much of its use seemed to be down-casting and generally violating OO rules. These days one hopes it is used more sensibly and appropriately.Kostival
@Duncan: I agree. Before introducing some explicit RTTI handling, in my designs, I ask myself: "In this situation, is this a code smell?", and indeed I sometimes end up modifying a few interfaces, refactoring somehow and avoiding the use of reflection.Singsong
A fantastic use of RTTI is by boost::any.Bullheaded
I'd argue that any time you find yourself using RTTI you need to take a good hard look at your design. That's not the same as saying, "Don't use it." I'm just saying it should make you consider carefully whether there might be alternatives.Molnar
M
3

I can think of exactly one case when it would be appropriate to use RTTI, and it doesn't even work.

It is fairly common for C-compatible APIs which perform callbacks to provide a user-defined void* to communicate a state structure back to the caller. When calling such an API from C++, it is quite common to pass the this pointer through said void* argument. From the callback, one might want to invoke virtual functions on the passed pointer.

In some cases when the callback parameters are insecure (such as LPARAM of a Windows message), it is obviously desirable to validate the pointer before using it for a virtual call, by checking the hidden vfptr. dynamic_cast is the natural way to do this, but results in undefined behavior exactly when the object is invalid (IIRC, it is undefined behavior if the pointer is to anything except an object with a virtual table). So RTTI is utterly useless for preventing a shatter attack in this way.

Feel free to present any other valid use cases for RTTI, cause I'm totally unconvinced.

EDIT: boost::any got mentioned. As far as boost::any is concerned, you can disable RTTI and use the following typeid implementation:

typedef const void* typeinfo_nonrtti;
template <typename T> typeinfo_nonrtti typeid_nonrtti();
template <typename T> class typeinfo_nonrtti_helper
{
  friend typeinfo_nonrtti typeid_nonrtti<T>();
  static char unique;
};
template <typename T> char typeinfo_nonrtti_helper<T>::unique;

template <typename T>
typeinfo_nonrtti typeid_nonrtti() { return &typeinfo_nonrtti_helper<T>::unique; }
Millicentmillie answered 16/4, 2010 at 5:24 Comment(7)
Like I said above, boost::any. :)Bullheaded
Doesn't look like RTTI to me, it appears that it would use the compile-time type inferred during instantiation of the holder<ValueType> template. If it is RTTI, then you're in serious trouble because any_cast does an equality match based on the typeid, not a subclass match, so it would be effectively impossible to get the value back out (you'd have to any_cast to the exact runtime type of the object, not the type you put in, if the type is polymorphic). I've never used boost::any and based on a cursory examination of the source, never will. Too fragile.Millicentmillie
Excuse me, boost::any uses typeid(ValueType), not typeid(value). Therefore it's purely compile-time type information even if the type is polymorphic. Completely useless, you can get the same effect without typeid or any use of RTTI.Millicentmillie
Eh, it's still RTTI technically.Bullheaded
Did you read the code snippet I posted? RTTI is not needed to implement boost::any.Millicentmillie
@BenVoigt Actually, it is much easier: template <typename T> typeinfo_non_rtti typeid_non_rtti() { static char unique = 0; return &unique; }Mile
@zen-cat: I think that implementation may cause issues if COMDAT folding is enabled. But thanks for making me take a second look at this code and add the missing static.Millicentmillie

© 2022 - 2024 — McMap. All rights reserved.