#ifndef CHECKED_CAST_H
#define CHECKED_CAST_H


#ifndef FLAW_H
#include "Flaw.h"
#endif

//#include <typeinfo.h>

namespace MM
{

template <typename Target, typename Source> inline Target *
ptr_cast (Source * source)
{
    #ifndef NDEBUG
    Target *result = dynamic_cast <Target*> (source);
    if ( result == 0)
        //FLAW (Text() 
        //    + typeid(Source).name() + " AND " 
        //    + typeid(Target).name() + " are incompatible types." );
        FLAW ("Incompatible type.");
    else
        return result;
    #endif

    return static_cast <Target*> (source);
}

template <typename Target, typename Source> inline Target &
ref_cast (Source & source)
{
    #ifndef NDEBUG
    try
    {
        return dynamic_cast <Target&> (source);
    }
    catch(...)
    {
        //throw "ref_cast(): incompatible type.";
        FLAW ("Incompatible type.");
    }
    #endif

    return static_cast <Target&> (source);
}

template <typename Target, typename Source> inline Target
cast (Source & source)
{
    #ifndef NDEBUG
    return dynamic_cast <Target> (source);
    #else
    return static_cast <Target> (source);
    #endif
}

/*
template <typename Target, typename Source> inline Target 
checked_cast (Source *& source)
{
    #ifndef NDEBUG
    Target *result = dynamic_cast <Target> (source);
    if ( result == 0)
        FLAW ("Incompatible type.");
    else
        return result;
    #endif

    return static_cast <Target> (source);
}

template <typename Target, typename Source> inline Target 
checked_cast (Source & source)
{
    #ifndef NDEBUG
    try
    {
        return dynamic_cast <Target> (source);
    }
    catch(...)
    {
        FLAW ("Incompatible type.");
    }
    #endif

    return static_cast <Target> (source);
}//*/

}//MM

#endif//CHECKED_CAST_H
