This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| Run Time Type Information Submitted by

The other day we tracked a bad bug where a base class was been cast to the wrong thing. The reason why it happed was because we didn't have any RTTI (Run Time Type Information) in place. We also didn't want to use the one that it comes with the compiler for fear that it will add "evil" code. So after hitting that bug I decided to do my on RTTI. I wanted to be simple and very fast. This is what we use now. It looks kind of neat so I thought to share it. Enjoy.

Download Associated File: rtti.txt (5,153 bytes)

    /*

    The other day we tracked a bad bug where a base class was been cast to
    the wrong thing.
    The reason why it happed was because we didn't have any RTTI (Run Time
    Type Information) in place.
    We also didn't want to use the one that it comes with the compiler for
    fear that it will add "evil" code.
    So after hitting that bug I decided to do my on RTTI. I wanted to be
    simple and very fast.
    This is what we use now. It looks kind of neat so I thought to share it.
    Enjoy.

    Tomas
    tarce@zen-x.net

    */

    #include <stdlib.h>
    #include <assert.h>
    #include <string.h>
    //==============================================================================
    // RTTI
    //==============================================================================
    // Using the RTTI
    //------------------------------------------------------------------------------
    // struct base
    // {
    //     CREATE_RTTI_BASE( base );
    // };
    //
    // struct pepe : public base
    // {
    //     CREATE_RTTI( pepe, base, base )
    //     void Normal( void ){}
    // };
    //
    // struct super_pepe : public pepe
    // {
    //     CREATE_RTTI( super_pepe, pepe, base )
    //     void Super( void ){}
    // };
    //
    // void main( void )
    // {
    //     super_pepe SP;         // The original class
    //     base&      B = SP;     // Some generic base reference
    //
    //     // We want to safely convert to pepe
    //     pepe& P = pepe::GetSaveType( B );
    //
    //     // cast the base class right
    //     if( B.IsKindOf( super_pepe::GetRTTI() ) )
    //     {
    //         super_pepe& SP = super_pepe::GetSaveType( B );
    //         SP.Super();
    //     }
    //     else if( B.IsKindOf( pepe::GetRTTI() ) )
    //     {
    //         pepe& P = pepe::GetSaveType( B );
    //         P.Normal();
    //     }
    // }
    //==============================================================================
    #define CREATE_RTTI( TYPE, BASE_CLASS )
    #define CREATE_RTTI_BASE( TYPE )

    struct rtti
    {
        bool IsKindOf( const rtti& RTTI ) const;
             rtti    ( const char* pTypeName );
             rtti    ( const char* pTypeName, const rtti& RTTI );

        const char* pType;      // This is not really need it, just useful in debugger.
        const rtti& Next;
    };

    //==============================================================================
    // IMPLEMENTATION
    //==============================================================================
    #pragma warning( push )
    #pragma warning( disable : 4355 ) // warning 'this' used in base member initializer list
    #undef CREATE_RTTI
    #undef CREATE_RTTI_BASE

    inline rtti::rtti( const char* pTypeName ) :
    pType(pTypeName), Next( *this ){}

    inline rtti::rtti( const char* pTypeName, const rtti& RTTI ) :
    pType(pTypeName), Next( RTTI ){}

    inline bool rtti::IsKindOf( const rtti& RTTI ) const
    {
        const rtti* p = this;
        do
        {
            if( p == &RTTI    ) return true;
            if( p == &p->Next ) break;
            p = &p->Next;

        } while(1);
        return false;
    }

    #define PRIVATE_RTTI_FUNCTION_SET( TYPE, BASE_CLASS )                 \
        virtual inline const rtti& GetObjectRTTI( void ) const            \
        {                                                                 \
            return TYPE::GetRTTI();                                       \
        }                                                                 \
        inline const bool IsKindOf( const rtti& RTTI ) const              \
        {                                                                 \
            return GetObjectRTTI().IsKindOf( RTTI );                      \
        }                                                                 \
        static inline TYPE& GetSaveType( BASE_CLASS& Object )             \
        {                                                                 \
            assert( Object.IsKindOf(TYPE::GetRTTI()) );                   \
            return *((TYPE*)&Object);                                     \
        }                                                                 \
        static inline const TYPE& GetSaveType( const BASE_CLASS& Object ) \
        {                                                                 \
            assert( Object.IsKindOf(TYPE::GetRTTI()) );                   \
            return *((const TYPE*)&Object);                               \
        }

    #define CREATE_RTTI( TYPE, TYPE_PARENT, BASE_CLASS )                  \
        static  inline const rtti& GetRTTI( void )                        \
        {                                                                 \
            static rtti s_RTTI( #TYPE, TYPE_PARENT::GetRTTI() );          \
            return s_RTTI;                                                \
        }                                                                 \
        PRIVATE_RTTI_FUNCTION_SET(TYPE,BASE_CLASS)

    #define CREATE_RTTI_BASE( TYPE )                                      \
        static  inline const rtti& GetRTTI( void )                        \
        {                                                                 \
            static rtti s_RTTI( #TYPE );                                  \
            return s_RTTI;                                                \
        }                                                                 \
        PRIVATE_RTTI_FUNCTION_SET(TYPE,TYPE)

    #pragma warning( pop )

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.