Reputation: 2675
There are a lot of question on the subject, but none seem to address this specifically: Given a code base that does not allow everything solved with virtual functions (as you would do normally) there is a function:
/** Check if obj is a T, including base classes. */
template <class T>
inline bool is_a(const basic &obj)
{
return dynamic_cast<const T *>(&obj) != 0;
}
But obviously the cast is made even if unnecessary. How to write this function to check only, i.e., using the dynamic_cast
functionality without doing the actual cast? Assume that it is impractical to replace calls to this function with virtual functions, or to implement a poor man's RTTI for the purpose.
EDIT: added question mark to title emphasizing the doubt about the possibility
Upvotes: 1
Views: 2293
Reputation: 19721
Note that the actual cast is just adding an offset to the pointer. Any steps needed to determine that offset are also needed to determine whether the cast is possible at all. And a good optimizer will optimize out that final addition anyway, as adding a constant to a non-null pointer that is not used except for a null test does not have an effect.
Therefore any replacement that doesn't improve the design would have no measurable effect; the correct replacement if a better design is not possible for some reason is therefore to leave the function as it is.
Upvotes: 5
Reputation: 26486
dynamic_cast()
will also fail if the base class is not polymorphic , meaning it doesn't have any virtual methods. meaning that B may inherit from A, but dynamic_cast()
on B* to A* will fail because A doesn't have any virtual function .
luckily , we have C++11 : std::is_base_of<>
: http://en.cppreference.com/w/cpp/types/is_base_of
which works even if A and B aren't polymorphic , and it also works on compile time, meaning no run-time overhead
Example :
class A {};
class B : public A{};
int main (){
B b;
if (std::is_base_of<A,decltype(b)>::value){
std::cout<<"b can be up-cast to A*";
}
return 0;
}
(can be viewed in : http://coliru.stacked-crooked.com/a/a5612738047ff3a5)
make sure to remove any reference or pointer beforehand with std::remove_pointer
and std::remove_reference
if dealing with with them
Upvotes: 1
Reputation: 146910
There is no equivalent functionality. You've only got two alternatives.
I don't know why you even care about preventing the pointer adjustment, because it's a fairly trivial case of a couple of vtable lookups (into vtables that are already in cache) and performing a couple of subtractions. All of the actual work of dynamic_cast
would be done in both cases. Furthermore, I don't see what use the result of is_a
would be without casting the pointer to that type.
There is no easy way to do what you want, principally because it doesn't really make sense and therefore nobody decided to provide it.
Upvotes: 1