I l@ve RuBoard Previous Section Next Section

2.8 A Wrapper Around type_info

Standard C++ provides the std::type_info class, which gives you the ability to investigate object types at runtime. You typically use type_info in conjunction with the typeid operator. The typeid operator returns a reference to a type_info object:



void Fun(Base* pObj)


{


   // Compare the two type_info objects corresponding


   // to the type of *pObj and Derived


   if (typeid(*pObj) == typeid(Derived))


   {


      ... aha, pObj actually points to a Derived object ...


   }


   ...


}


The typeid operator returns a reference to an object of type type_info. In addition to supporting the comparison operators operator== and operator!=, type_info provides two more functions:

  • The name member function returns a textual representation of a type, in the form of const char*. There is no standardized way of mapping class names to strings, so you shouldn't expect typeid(Widget) to return "Widget". A conforming (but not necessarily award-winning) implementation can have type_info::name return the empty string for all types.

  • The before member function introduces an ordering relationship for type_info objects. Using type_info::before, you can perform indexing on type_info objects.

Unfortunately, type_info's useful capabilities are packaged in a way that makes them unnecessarily hard to exploit. The type_info class disables the copy constructor and assignment operator, which makes storing type_info objects impossible. However, you can store pointers to type_info objects. The objects returned by typeid have static storage, so you don't have to worry about lifetime issues. You do have to worry about pointer identity, though.

The standard does not guarantee that each invocation of, say, typeid(int) returns a reference to the same type_info object. Consequently, you cannot compare pointers to type_info objects. What you should do is to store pointers to type_info objects and compare them by applying type_info::operator== to the dereferenced pointers.

If you want to sort type_info objects, again you must actually store pointers to type_info, and this time you must use the before member function. Consequently, if you want to use STL's ordered containers with type_info, you must write a little functor and deal with pointers.

All this is clumsy enough to mandate a wrapper class around type_info that stores a pointer to a type_info object and provides

  • All the member functions of type_info

  • Value semantics (public copy constructor and assignment operator)

  • Seamless comparisons by defining operator< and operator==

Loki defines the wrapper class TypeInfo which implements such a handy wrapper around type_info. The synopsis of TypeInfo follows.



class TypeInfo


{


public:


   // Constructors/destructors


   TypeInfo(); // needed for containers


   TypeInfo(const std::type_info&);


   TypeInfo(const TypeInfo&);


   TypeInfo& operator=(const TypeInfo&);


   // Compatibility functions


   bool before(const TypeInfo&) const;


   const char* name() const;


private:


   const std::type_info* pInfo_;


};


// Comparison operators


bool operator==(const TypeInfo&, const TypeInfo&);


bool operator!=(const TypeInfo&, const TypeInfo&);


bool operator<(const TypeInfo&, const TypeInfo&);


bool operator<=(const TypeInfo&, const TypeInfo&);


bool operator>(const TypeInfo&, const TypeInfo&);


bool operator>=(const TypeInfo&, const TypeInfo&);


Because of the conversion constructor that accepts a std::type_info as a parameter, you can directly compare objects of type TypeInfo and std::type_info, as shown:



void Fun(Base* pObj)


{


   TypeInfo info = typeid(Derived);


   ...


   if (typeid(*pObj) == info)


   {


      ... pBase actually points to a Derived object ...


   }


   ...


}


The ability to copy and compare TypeInfo objects is important in many situations. The cloning factory in Chapter 8 and one double-dispatch engine in Chapter 11 put TypeInfo to good use.

    I l@ve RuBoard Previous Section Next Section