⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dobase.hpp

📁 The library provides supports for run-time loaded plugin classes in C++
💻 HPP
📖 第 1 页 / 共 2 页
字号:
    DO_ASSERT( (int)DoIsConst<U>::v >= (int)DoIsConst<T>::v );    DO_ASSERT( IsVObj<T>::v );	return *DoCasterStr< typename DoBaseType<U>::type*, DoIsTypeA<T,DynI>::v, DoIsTypeA<T,RTDynShared>::v >::Cast(&t,algo);}/** @ingroup DynTemplate * Cast arbitrary type to VObj if it can be safely done.  * If T is not a VObj, it generates a compile time error. * @param t a pointer/reference/instance of any type * @return a pointer to a VObj (the same object) if this can be done. */template<class T>VObj *to_vobj( T t ) {    DO_ASSERT( IsVObj<T>::v );	return reinterpret_cast<VObj*>(t);}template<class T>VObj &to_vobj( T& t ) {    DO_ASSERT( IsVObj<T>::v );	return reinterpret_cast<VObj&>(t);}template<class T>struct doTypeWrapper{ };///////////////////////////////////////////////////////// DynData - temporary arbitrary type data holder//#include <string.h>#include <assert.h>#include "DoTypeBase.hpp"#define DYNDATA_MAX_SIZE sizeof(double)/** @ingroup DynI  * Store/retrieve any datatype at run-time.  * Dynamically typed data holder. Stores data any (most) run-time data together  * with its type. The most important use is together with DynObj constructors.  */// %%DYNOBJ class(dyni) flags(notypeid,inst2reg)class DynData : public DynI { public:    DynObjType* docall doGetType( const DynI **pself ) const;        DynData( ) : m_type(0) { }        /** @name Main interface */    //@{        /** Constructor, takes arbitrary type. */    template<class T>    DynData( T t ) {        // Check that size is OK        DO_ASSERT( sizeof(T) <= DYNDATA_MAX_SIZE );                m_type = DoFullType2Int<T>::Id();                // Fill up with 0 or -1 if signed        memset( m_data, ((m_type&DOT_TYPE_MASK)==DOT_SINT)?-1:0, DYNDATA_MAX_SIZE );        #ifdef PFM_BIG_ENDIAN                // Motorola style, value stored at end        *(T*)(m_data+DYNDATA_MAX_SIZE-sizeof(T)) = t;#else        // Intel style, value always stored first        *(T*)m_data = t;#endif    }        /** Returns current type id.      * @return full type ID including pointer level, const and ref      */    int GetType(){ return m_type; }        /** Check if the DynData can return requested type without loosing precision.     * This mainly follows C++ casting rules.      * @return true if type can be cast to, false otherwise.     */    template<class T>    bool IsA() const {        int type = DoFullType2Int<T>::Id();        if( type==UNKNOWN_TYPE_ID ) return false;                if( type==m_type ||             // Exactly the same type            type==(m_type|DOT_CONST) )  // or a const version is asked for             return true;                    // If wrong pointer/ref level, we fail        if( DOT_PTR_REF_LEVEL(type)!=DOT_PTR_REF_LEVEL(m_type) ) return false;        // OK const-ness? Out must be equal or more const        if( !(type&DOT_CONST) && (m_type&DOT_CONST) ) return false;                    // Request for a user-type ?        if( !(type&DOT_PRIMITIVE) ){            // If we are a primitive type, fail.            if( m_type&DOT_PRIMITIVE ) return false;                        // We check if the requested type is a direct base class of ours            DynObjType *dot = doFindType(m_type&TYPE_ID_MASK);            if( !dot ){                VObj::SetError( "DynData::IsA - Failed looking up DynObjType", m_type );                return false;            }            // ## This asks type from callers module. Code should be (and is)            // in callers module.            // See if we have this class as a main base class            return dot->IsA( type&TYPE_ID_MASK );        }        // If we are a user type, the only primitive type we can convert        // to is const void* or bool        if( !(m_type&DOT_PRIMITIVE) ) {            // Must be pointer or ref            if( !(m_type&(DOT_PTR_MASK|DOT_REF)) ) return false;            return type==DoType2Int<const void*>::v ||                    type==DoType2Int<bool>::v;        }                    // Both are primitive types                // Same base type? (char/signed int/unsigned int)        if( (type&DOT_TYPE_MASK)==(m_type&DOT_TYPE_MASK) ){            // We can expand a small integer/char to a larger one        	if( (type&DOT_SIZE_MASK)>=(m_type&DOT_TYPE_MASK) )        		return true;        	// We could also check that our value is in the requested range        	// That is really a run-time check            // I.e int(5) could be casted to unsigned int            // but int(-2) could not        }                return false;    }        /** Cast to requested type.     * This can be applied after checking the IsA function above. If type is      * not supported a run-time assert happens.     * @return The internal value casted to requested type without any loss of precision.     */    template<class T>    T Get() const {		bool b = IsA<T>();        assert( b ); // # Is this a good solution? Maybe better to set object error.        // We must request either a const reference or         // not a reference at all.        DO_ASSERT( DoIsConst<T>::v ||                    !(DoIsRef<T>::v && !DoIsPointer<T>::v) );                   #ifdef PFM_BIG_ENDIAN                // Motorola style, value stored at end        return *reinterpret_cast<const T*>(m_data+DYNDATA_MAX_SIZE-sizeof(T)); #else        // Intel style, value always stored first        return *reinterpret_cast<const T*>(m_data); #endif    }    //@}/*    // Basically we want the same signature without args.    double GetDouble() const {        assert( m_type&DOT_TYPE_MASK==DOT_FLOAT );        switch( m_type&DOT_SIZE_MASK ){#ifdef PFM_BIG_ENDIAN                    case DOT_SIZE_8: return (double)*reinterpret_cast<const float*>(m_data+DYNDATA_MAX_SIZE-sizeof(double));#else            case DOT_SIZE_8: return *reinterpret_cast<const double*>(m_data);#endif            #ifdef PFM_BIG_ENDIAN                    case DOT_SIZE_4: return (double)*reinterpret_cast<const float*>(m_data+DYNDATA_MAX_SIZE-sizeof(float));#else            case DOT_SIZE_4: return (double)*reinterpret_cast<const float*>(m_data);#endif            default: assert(0);        }        return 0.0;    }*/        // We could also provide:    //   bool CanBeA()    // and     //   T Extract()     // which would allow for converting/lossy casts    protected:    int m_type;	union {		char m_data[DYNDATA_MAX_SIZE];		const char* m_str;		// For debugging convenience	};};/** @ingroup DynTemplate * Wrapper around a C++ reference to an instance.  * C++ cannot have both a function that takes an instance * and a function that takes a reference to an instance. This  * template allows to keep the reference without instantiating. * Used in the dispatch functions below (do_try). */template<class T>struct doKeepRef {    doKeepRef( T& t ) : m_t(t) { }    operator T& (){ return m_t; }    T& m_t;};/** @ingroup DynTemplate * A template to try to execute a single function on another interface. * The function and arguments are passed along, and a default return value  * as last argument (0 if not specified). * If cast to the other interface fails, the default value is returned. * A reference cannot be returned in this way. */template<class I>void do_try( DynI *pdi, void (I::*func)() ){	I *pi = do_cast<I*>(pdi);	if( pi ) (pi->*func)();}/** @ingroup DynTemplate * As above, but no args, return value */template<class I, class RV>RV do_try( DynI *pdi, RV (I::*func)(), RV rv=0 ){	I *pi = do_cast<I*>(pdi);	if( !pi ) return rv;	return (pi->*func)();}/** @ingroup DynTemplate * As above, one arg, no return value */template<class I, class A1, class _A1>void do_try( DynI *pdi, void (I::*func)(A1), _A1 a1 ){	I *pi = do_cast<I*>(pdi);	if( pi ) (pi->*func)(a1);}/** @ingroup DynTemplate * As above, one arg, return value */template<class I, class RV, class A1, class _A1>RV do_try( DynI *pdi, RV (I::*func)(A1), _A1 a1, RV rv=0 ){	I *pi = do_cast<I*>(pdi);	if( !pi ) return rv;	return (pi->*func)(a1);}/** @ingroup DynTemplate * As above, two args, no return value */template<class I, class A1, class A2,                   class _A1, class _A2>void do_try( DynI *pdi, void (I::*func)(A1,A2), _A1 a1, _A2 a2 ){	I *pi = do_cast<I*>(pdi);	if( pi ) (pi->*func)(a1,a2);} /** @ingroup DynTemplate * As above, two args, return value */template<class I, class RV, class A1, class A2,                             class _A1, class _A2>RV do_try( DynI *pdi, RV (I::*func)(A1,A2), _A1 a1, _A2 a2, RV rv=0 ){	I *pi = do_cast<I*>(pdi);	if( !pi ) return rv;	return (pi->*func)(a1,a2);}template<class I, class A1, class A2, class A3,                   class _A1, class _A2, class _A3>void do_try( DynI *pdi, void (I::*func)(A1,A2,A3), _A1 a1, _A2 a2, _A3 a3 ){	I *pi = do_cast<I*>(pdi);	if( pi ) (pi->*func)(a1,a2,a3);} // No args, return valuetemplate<class I, class RV, class A1, class A2, class A3,                             class _A1, class _A2, class _A3>RV do_try( DynI *pdi, RV (I::*func)(A1,A2,A3), _A1 a1, _A2 a2, _A3 a3, RV rv=0 ){	I *pi = do_cast<I*>(pdi);	if( !pi ) return rv;	return (pi->*func)(a1,a2,a3);}// %%DYNOBJ section general// This section is auto-generated and manual changes will be lost when regenerated!!#ifdef DO_IMPLEMENT_DOBASE    #define DO_IMPLEMENTING     // If app has not defined it already#endif#include "dynobj/DynObj.h"// --- Forward class declarations ---class DynData;// --- For each declared class, doTypeInfo template specializations ---DO_DECL_TYPE_INFO(DynData,DYNDATA_TYPE_ID);// %%DYNOBJ section end// %%DYNOBJ section implement// This section is auto-generated and manual changes will be lost when regenerated!!#ifdef DO_IMPLEMENT_DOBASE// Generate type information that auto-registers on module loadDynObjTypeI2R<DynData,DynI,false> g_do_vtype_DynData("DynData:DynI",DYNDATA_TYPE_ID,1);DynObjType* DynData::doGetType( const DynI **pself ) const {   if(pself) *pself=(const DynI*)(const void*)this;   return &g_do_vtype_DynData;}#endif //DO_IMPLEMENT_...// %%DYNOBJ section end#endif //DOBASE_HPP

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -