📄 dobase.hpp
字号:
// Copyright (c) 2007, Arne Steinarson// Licensing for DynObj project - see DynObj-license.txt in this folder#ifndef DOBASE_HPP#define DOBASE_HPP#include <string.h>// Basic interfaces#include "DoBaseI.h"#include "DoError.h"// Include DynShared support#if DO_USE_DYNSHARED==1 #include "DoDynShared.hpp"#endif// Doxygen stuff/// @cond internal///////////////////////////////////// This compile-time assert is adopted from Boosttemplate<bool b>struct DoErrorIfNot;template<>struct DoErrorIfNot<true>{ };#define DO_ASSERT(cond) sizeof(DoErrorIfNot<cond>)//////////////////////////////////////// Peel off pointers, refs & consttemplate <class T>struct DoBaseType { typedef T type;};template <class T>struct DoBaseType<T*> { typedef typename DoBaseType<T>::type type;};template <class T>struct DoBaseType<T&> { typedef typename DoBaseType<T>::type type;};template <class T>struct DoBaseType<const T> { typedef typename DoBaseType<T>::type type;};/////////////////////////////////////////// Simple test for same typetemplate <class T, class U>struct IsSameType { enum { v=false };};template <class T>struct IsSameType<T,T> { enum { v=true };};///////////////////////////////////////////////// Tests if a class has a VTable or nottemplate<class T>struct IsVObjImpl { struct IA : public T { int m; }; struct IB : public T { virtual void F( ); int m; }; enum { v = (sizeof(IA)==sizeof(IB)) }; };/// @endcond internal/** @ingroup DynTemplate * Test if a type has a VTable or not. * @return v is set to true if type has a VTable and false otherwise. */template<class T>struct IsVObj { typedef typename DoBaseType<T>::type type; enum { v=IsVObjImpl<type>::v || IsSameType<VObj,type>::v };};/// @cond internal/*template<class T>struct IsVObj<T*> { enum { v = IsVObj<T>::v };};template<class T>struct IsVObj<T&> { enum { v = IsVObj<T>::v };};*/// This avoids long error messages for the void casetemplate<> struct IsVObj<void> { enum { v = false };};///////////////////////////////////////////////////// Is a class derived from DynI?template <class T, class U>struct DoIsTypeAImpl { // Test functions static char F( U* ); static short F(...); static T* pt; enum { v=sizeof(F(pt))==sizeof(char) };};template <class T, class U>struct DoIsTypeA { enum { v=DoIsTypeAImpl<typename DoBaseType<T>::type,U>::v };};// Check if type is consttemplate <class T>struct DoIsConst { enum { v=0 };};template <class T>struct DoIsConst<const T> { enum { v=1 };};template <class T> // Should this be needed?struct DoIsConst<const T&> { enum { v=1 };};template <class T> // Should this be needed?struct DoIsConst<const T*> { enum { v=1 };};/////////////////////////////////////////// Check if type is ref or nottemplate <class T>struct DoIsRef { enum { v=0 };};template <class T>struct DoIsRef<T&> { enum { v=1 };};/////////////////////////////////////////// Check if type is ref or nottemplate <class T>struct DoIsPointer { enum { v=0 };};template <class T>struct DoIsPointer<T*> { enum { v=1 };};// Casting based on type ID:stemplate<class U, int M, int N>struct DoCaster; // Generic case, compile time errortemplate<class U, int N>struct DoCaster<U,0,N> { // Case for detected VObj static U Cast( const void *pv, doCastAlgo algo ){ if( !pv ) return 0; return reinterpret_cast<U>(::doGetObj((void*)pv,doTypeInfo<U>::Id(),NULL,algo)); }};template<class U, int N>struct DoCaster<U,1,N> { // Case for DynI static U Cast( const DynI *pdi, doCastAlgo algo ) { if( !pdi ) return 0; return reinterpret_cast<U>(::doGetObj((void*)pdi,doTypeInfo<U>::Id(),DI_GET_TYPE(pdi),algo)); }};#if DO_USE_DYNSHARED==1template<class U, int N>struct DoCaster<U,N,1> { // Case for RTDynShared static U Cast( const RTDynShared *prtds, doCastAlgo algo ) { if( !prtds ) return 0; // Return pointer to self? if( IsSameType<U,DynSharedI>::v || IsSameType<U,DynI>::v || IsSameType<U,VObj>::v ) return prtds; else return DoCaster<U,2,0>::Cast( prtds, algo ); }};#else // DO_USE_DYNSHARED // Provide dummy template class for test below struct RTDynShared { };#endif// Type-string case (for do_cast_str)template<class U, int M, int N>struct DoCasterStr; // Generic case, compile time errortemplate<class U, int N>struct DoCasterStr<U,0,N> { // Case for detected VObj static U Cast( const void *pv, doCastAlgo algo ){ if( !pv ) return 0; return reinterpret_cast<U>(::doGetObj((void*)pv,doTypeInfo<U>::Name(),NULL,algo)); }};template<class U, int N>struct DoCasterStr<U,1,N> { // Case for DynI static U Cast( const DynI *pdi, doCastAlgo algo ) { if( !pdi ) return 0; return reinterpret_cast<U>(::doGetObj((void*)pdi,doTypeInfo<U>::Name(),DI_GET_TYPE(pdi),algo)); }};#if DO_USE_DYNSHARED==1template<class U, int N>struct DoCasterStr<U,N,1> { // Case for RTDynShared static U Cast( const RTDynShared *prtds, doCastAlgo algo ) { if( !prtds ) return 0; // Return pointer to self? if( IsSameType<U,DynSharedI>::v || IsSameType<U,DynI>::v || IsSameType<U,VObj>::v ) return prtds; else return DoCasterStr<U,2,0>::Cast( prtds, algo ); }};#endif/// @endcond internal/** @ingroup DynTemplate * Cast a pointer to another C++ type across DLL/SO boundaries. * This does type lookup using information from the library compiler. * It is the equivalent of dynamic_cast in C++ or QueryInterface in COM. * It uses integer type ID:s internally (not type strings) and is therefore * faster then string based casts. * @return a pointer to the requested interface/class if found, otherwise NULL. */template<class U, class T>U do_cast( T* pt, doCastAlgo algo=doCastCross ) { // OK when we have positive on IsVObj or IsDynI, // negative when both are false (compile time error, we // cannot cast from the type). // Verify constness first (compile time) DO_ASSERT( DoIsConst<U>::v || !DoIsConst<T>::v ); DO_ASSERT( IsVObj<T>::v ); return DoCaster< U, DoIsTypeA<T,DynI>::v, DoIsTypeA<T,RTDynShared>::v >::Cast(pt,algo);}/** @ingroup DynTemplate * Cast a reference to another C++ type across DLL/SO boundaries. * This does type lookup using information from the source object compiler. * It is the equivalent of dynamic_cast in C++ or QueryInterface in COM. * It uses integer type ID:s internally (not type strings) and is therefore * faster then string based casts. * @return a pointer to the requested interface/class if found, otherwise NULL. */template<class U, class T>U do_cast_ref( T& t, doCastAlgo algo=doCastCross ) { // Verify constness first (compile time) DO_ASSERT( (int)DoIsConst<U>::v >= (int)DoIsConst<T>::v ); DO_ASSERT( IsVObj<T>::v ); // Then cast return *DoCaster< typename DoBaseType<U>::type*, DoIsTypeA<T,DynI>::v, DoIsTypeA<T,RTDynShared>::v >::Cast(&t,algo);}/** @ingroup DynTemplate * As above but uses type strings (and can therefore find custom objects). * Using string based casts is slower than casts based on integer ID. * @return a pointer to the requested interface/class if found, otherwise NULL. */template<class U, class T>U do_cast_str( T* pt, doCastAlgo algo=doCastCross ) { // Verify constness first (compile time) DO_ASSERT( DoIsConst<U>::v || !DoIsConst<T>::v ); DO_ASSERT( IsVObj<T>::v ); return DoCasterStr< U, DoIsTypeA<T,DynI>::v, DoIsTypeA<T,RTDynShared>::v >::Cast(pt,algo);}/** @ingroup DynTemplate * As above but uses type strings and for references. * @return a referece to the requested interface/class if found, otherwise NULL. */template<class U, class T>U do_cast_ref_str( T& t, doCastAlgo algo=doCastCross ) { // Verify constness first (compile time)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -