I l@ve RuBoard |
![]() ![]() |
2.8 A Wrapper Around type_infoStandard 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:
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
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 |
![]() ![]() |