Adding Exceptions & RTTI to the Windows CE Compiler: Part I
by Dani Carles

Listing One
// Gotcha using TCU_RTTI_DECLARE. Member access changed to public.
class A : public tcu_Rtti
{
public:
    A();
    ~A();
private:
    TCU_RTTI_DECLARE;       // Public access from here on
    int mv_anInt;           // Oops ! No longer private
};
// To avoid the above, always declare RTTI at the end of your class.
class A : public tcu_Rtti
{
public:
    A();
    ~A();
private:
   int mv_anInt;
    TCU_RTTI_DECLARE;      // OK now given this is the last statement
                           // in the class declaration
};


Listing Two
// File: tcutest.h
#include <iostream>
#include <string>
#include <exception>
#include "tcurtti.h"
#include "tcuexc.h"

// Exception-sensitive object to be destroyed during stack unwinding
// It also contains RTTI info
class UnwindableObj : public tcu_Rtti, virtual protected tcu__Xsc
{
    // Only public base classes should be accessible via dynamic_cast
    typedef tcu_Rtti Base;
    static unsigned int mv_nCount;
public:
    // Default constructor
    UnwindableObj()
    {
        TCU_X_RESET;
        std::cout << "UnwindableObj ctor for 0x" << this << std::endl;
        mv_nCount++;
    }
    // Copy constructor
    UnwindableObj(const UnwindableObj &u) : tcu__Xsc(u), tcu_Rtti(u)
    {
        TCU_X_RESET;
        std::cout << "UnwindableObj copy ctor for 0x" << this << std::endl;
        mv_nCount++;
    }
    // Destructor
    virtual ~UnwindableObj()
    {
        std::cout << "UnwindableObj dtor for 0x" << this << std::endl;
        mv_nCount--;
    }
    // Accessor
    static unsigned int getCtorCount()
    {
        return mv_nCount;
    }
    TCU_RTTI_DECLARE;
};
inline TCU_RTTI_IMPLEMENT(UnwindableObj);
// Derived class to show RTTI at work
class DerivedObj : public UnwindableObj
{
    typedef UnwindableObj Base;
public:
    // Default constructor
    DerivedObj()
    {
        TCU_X_RESET;
        std::cout << "DerivedObj ctor for 0x" << this << std::endl;
    }
    // Copy constructor
    DerivedObj(const DerivedObj &d) : UnwindableObj(d)
    {
        TCU_X_RESET;
        std::cout << "DerivedObj copy ctor for 0x" << this << std::endl;
    }
    // Destructor
    virtual ~DerivedObj()
    {
        std::cout << "DerivedObj dtor for 0x" << this << std::endl;
    }
    // New class method
    void DerivedMethod()
    {
        std::cout << "DerivedMethod()" << std::endl;
    }
    TCU_RTTI_DECLARE;
};
inline TCU_RTTI_IMPLEMENT(DerivedObj);
// Exception base class
class ExcBase TCU_COLON_XC, public UnwindableObj, public std::exception
{
    std::string mv_msg;
public:
    // Default constructor
    ExcBase(std::string msg) : mv_msg(msg)
    {
        TCU_X_RESET;
        std::cout << "ExcBase ctor for 0x" << this << std::endl;
    }
    // Copy constructor
    ExcBase(const ExcBase &e) : tcu_Xc(e), UnwindableObj(e)
    {
        TCU_X_RESET;
        std::cout << "ExcBase copy ctor for 0x" << this << std::endl;
        mv_msg = e.what();
    }
    // Destructor
    virtual ~ExcBase()
    {
        std::cout << "ExcBase dtor for 0x" << this << std::endl;
    }
    // Retrieve error message
    TCU_RTTI_DECLARE;
};
inline TCU_RTTI_IMPLEMENT_2(ExcBase,tcu_Xc,UnwindableObj);
// Another exception class derived from above
class ExcDerived : public ExcBase
{
    typedef ExcBase Base;
public:
    // Default constructor
    ExcDerived(std::string msg) : ExcBase(msg)
    {
        TCU_X_RESET;
        std::cout << "ExcDerived ctor for 0x" << this << std::endl;
    }
    // Copy constructor
    ExcDerived(const ExcDerived &e) : ExcBase(e)
    {
       TCU_X_RESET;
       std::cout << "ExcDerived copy ctor for 0x" << this << std::endl;
    }
    // Destructor
    virtual ~ExcDerived()
    {
        std::cout << "ExcDerived dtor for 0x" << this << std::endl;
    }
    TCU_RTTI_DECLARE;
};
inline TCU_RTTI_IMPLEMENT(ExcDerived);



Listing Three
#include <iostream>
#include <cassert>
#include "tcutest.h"

using namespace std;

// File scope functions
namespace {
void foo()
{
    cout << "In foo() ..." << endl;
    UnwindableObj foo1,foo2;
    TCU_X_THROW(ExcDerived("Derived exception"));
}
}
// Static member definition
unsigned int UnwindableObj::mv_nCount = 0;
// main
int main()
{
    cout << "Test of an EH working case using the original TCU library"
         << endl << endl;
    // EH test
    TCU_X_TRY
    {
        DerivedObj d;
        foo();
    }
    TCU_X_CATCH(ExcDerived,e)
    {
        cout << "ExcDerived caught: " << e.what() << " (0x" << &e << ")"
             << endl;
    }
    TCU_X_CATCH(ExcBase,e)
    {
        cout << "ExcBase caught: " << e.what() << " (0x" << &e << ")" << endl;
    }
    TCU_X_CATCH_ALL
    {
        cout << "Unknown exception" << endl;
    } TCU_X_END_TRY
    assert(UnwindableObj::getCtorCount() == 0);
    // RTTI test
    cout << endl<< "RTTI test" << endl << endl;
    UnwindableObj *pB = new DerivedObj();
    // Downcast
    DerivedObj *pD = tcu_rttiDynamicCast<DerivedObj>(pB);
    cout << "pD = 0x" << pD << endl;
    pD->DerivedMethod();
    // Typeid
    bool b = tcu_rttiTypeId(*pB) == TCU_RTTI_TYPE_ID(DerivedObj);
    cout << "TypeId test: " <<b << endl;
    delete pB;
    cout << "Press Enter to exit" << endl;
    cin.get();
    return 0;
}

