A simple Type mechanism for the Smallest Attribute System

The Smallest Attribute System (part 1, part 2) is almost done. This article presents a simple type mechanism that for eliminating the need for using C++ run time type information (RTTI). This modification is necessary because some compilers, especially on game consoles and embedded systems, don't generate RTTI. The last piece, still to come, is reading and writing attributes from a file.

An int or short can be substituted for the typeid in the Smallest Attribute System. The version presented here is self-priming; an identifier for a type is generated whenever a type is first requested by name. The next time the same type is requested, the generated id will be returned.

class CharPtrPredicate { public: bool operator()(char const*const& lhs, char const*const& rhs) const  { return strcmp(lhs, rhs) < 0; } }; static std::map<const char*, int, CharPtrPredicate> typeIds; static std::map<int, const char*> typeNames; // If a type hasn't been seen before, enumerate it, otherwise return // the enumerant generated the first time it was seen int GetTypeId(const char* type) { static int unique = 0; std::map<const char*, int, CharPtrPredicate>::const_iterator i = typeIds.find(type); int result; if (i == typeIds.end()) { typeIds[type] = unique; typeNames[unique] = type; result = unique; ++unique; } else  { result = i->second; } return result; } // GetTypeId must have been called for every type for this to return a useful value. const char* GetTypeName(int i) { std::map<int, const char*>::const_iterator j = typeNames.find(i); return j == typeNames.end() ? 0 : j->second; } 

The TypeName method needs to be updated.

std::string AttributeBinder::AttributeDescriptor::TypeName() const { return GetTypeName(typeId); }

Routines that use a particular type should statically initialize their variables to avoid map lookups later. For example:

 static int stringType = GetTypeId("std::string");   if (typeId == intType) o << "Found an int";

Finally modify the AttributeBinder to store an int as a typeId, instead of the type_info of the original class. The BIND macro needs to be modified as follows, everything else is pretty much the same.

#define BIND(className, val, vartype) \ binding.bind(#val, #vartype, (ptrdiff_t)&((className*)0)->val)

Content by Nick Porcino (c) 1990-2011