Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird use of `?:` in `typeid` code

In one of the projects I'm working on, I'm seeing this code

struct Base {   virtual ~Base() { } };  struct ClassX {   bool isHoldingDerivedObj() const {     return typeid(1 ? *m_basePtr : *m_basePtr) == typeid(Derived);   }   Base *m_basePtr; }; 

I have never seen typeid used like that. Why does it do that weird dance with ?:, instead of just doing typeid(*m_basePtr)? Could there be any reason? Base is a polymorphic class (with a virtual destructor).

EDIT: At another place of this code, I'm seeing this and it appears to be equivalently "superfluous"

template<typename T> T &nonnull(T &t) { return t; }  struct ClassY {   bool isHoldingDerivedObj() const {     return typeid(nonnull(*m_basePtr)) == typeid(Derived);   }   Base *m_basePtr; }; 
like image 587
Johannes Schaub - litb Avatar asked Jul 22 '11 20:07

Johannes Schaub - litb


1 Answers

I think it is an optimisation! A little known and rarely (you could say "never") used feature of typeid is that a null dereference of the argument of typeid throws an exception instead of the usual UB.

What? Are you serious? Are you drunk?

Indeed. Yes. No.

 int *p = 0; *p; // UB typeid (*p); // throws 

Yes, this is ugly, even by the C++ standard of language ugliness.

OTOH, this does not work anywhere inside the argument of typeid, so adding any clutter will cancel this "feature":

 int *p = 0; typeid(1 ? *p : *p); // UB typeid(identity(*p)); // UB 

For the record: I am not claiming in this message that automatic checking by the compiler that a pointer is not null before doing a dereference is necessarily a crazy thing. I am only saying that doing this check when the dereference is the immediate argument of typeid, and not elsewhere, is totally crazy. (Maybe is was a prank inserted in some draft, and never removed.)

For the record: I am not claiming in the previous "For the record" that it makes sense for the compiler to insert automatic checks that a pointer is not null, and to to throw an exception (as in Java) when a null is dereferenced: in general, throwing an exception on a null dereference is absurd. This is a programming error so an exception will not help. An assertion failure is called for.

like image 139
curiousguy Avatar answered Oct 02 '22 17:10

curiousguy