Anda di halaman 1dari 4

/*-----------------------------------------------------------------------------Filename: Variant.hpp Author : Jeffrey Morgan Purpose : Variant and VariantRef are 'AnyTypes'.

They are used to abstract away the notion of type and let you just deal with data. These classes carry around the MetaType of the data they store, allow for them to do things like convert data back to it's static type or clone data. Date : 2012/06/18 All content (C) 2012 DigiPen (USA) Corporation, all rights reserved. ------------------------------------------------------------------------------*/ #pragma once #include "../Source/Utilities/ErrorLogger.hpp" namespace SqueakyClean { class VariantRef; TODO( "Make Variant and Variant Ref store data internally, if size < 128bytes" ) ; // The Variant class copies the data passed to it. It can be thought of as a // "Value" function argument. // // The Variant class is used when you want to pass data around but you don't // need to change the data you're passing. It's good for sending messages or // passing arguments to functions. class Variant { friend class VariantRef; public: Variant(); template <class T> Variant( const T &t ) : m_data( META( T )->CloneNewInstance( (MemPtr)&t ) ) , m_meta( META( T ) ) , m_isPointer( false ) {} template <class T> Variant( T *t ) : m_data(/* META( T )->CloneNewInstance(*/ (MemPtr)t /*)*/ ) , m_meta( META( T ) ) , m_isPointer( true ) {} Variant( const VariantRef &rhs ); Variant( const Variant &rhs ); ~Variant(); template <class T> T* Cast( void ) const { return reinterpret_cast<T*>( m_data ); } template<class T> T Convert() const { return VariantRef( *this ).Convert<T>(); }

const MetaData *GetMeta( void ) const { return m_meta; } MemPtr GetData( void ) const { return m_data; } bool IsPointer( void ) const { return m_isPointer; } private: MemPtr m_data; const MetaData *m_meta; bool m_isPointer; // pointer dtor should not be called }; namespace tr1 = std::tr1; // create different base class to select different overloaded functions with struct TypeValue{}; struct TypePointer{}; struct TypeReference{}; template <class T> struct GetTypeModifiers : TypeValue{ typedef T stripped; }; template <class T> struct GetTypeModifiers<T&> : TypeReference{ typedef T stripped; }; template <class T> struct GetTypeModifiers<T*> : TypePointer{ typedef T stripped; }; // The VariantRef class stores the actual data you give it and can be thought of // as a "Reference" function argument. // // VariantRefs are useful for when you want to get a value back from a function // or when you want to work with pointers to data (ie, like lerping a property ) class VariantRef { public: VariantRef(); VariantRef( MemPtr mem, const MetaData *meta ); VariantRef( const VariantRef &rhs ); VariantRef( const Variant &rhs ); template <class T> VariantRef( const T &t ) : m_data( (MemPtr)&t ) , m_meta( META( T ) ) {} template <class T> VariantRef( T *t ) : m_data( (MemPtr)t ) , m_meta( META( T ) ) {} ~VariantRef(); template <typename T> T* Cast( void ) const { return reinterpret_cast<T*>( m_data ); } template<class T> T Convert() const { return InternalConvert<GetTypeModifiers<T>::stripped> ( tr1::is_arithmetic<T>(), GetTypeModifiers<T>() ); }

template <class T> T NumberConvert( void ) const { if ( m_meta == META( T ) ) { return *Cast<T>(); } else { WARNING_IF( !m_meta->HasNumberConverter(), "Cannot convert type '%s' to type '%s'", m_meta->GetName(), META( T )->GetName() ); return (T)m_meta->ConvertToDouble( m_data ); } } template <typename T> T* SmartCast( void ) const { const MetaData *test = META( T ); if ( m_meta == META( T ) ) { return Cast<T>(); } return reinterpret_cast<T*>( m_meta->ConvertInstanceTo( m_data, META( T ) ) ); } template <typename T> void Set( const T &data ) { m_data = (MemPtr)&data; m_meta = META(T); } template <typename T> void Set( T *data ) { m_data = (MemPtr)data; m_meta = META(T); } void Set( MemPtr data, const MetaData *meta ) { m_data = data; m_meta = meta; } const MetaData *GetMeta( void ) const { return m_meta; } MemPtr GetData( void ) const { return m_data; } private: MemPtr m_data; const MetaData *m_meta; // Non numeric types template <class T> __forceinline T& InternalConvert( const tr1::false_type&, const TypeValue& ) c onst { return *SmartCast<T>(); } template <class T> __forceinline T& InternalConvert( const tr1::false_type&, const TypeReference& ) const { return *SmartCast<T>(); } template <class T> __forceinline T* InternalConvert( const tr1::false_type &, const TypePointer&

) const { return SmartCast<T>(); } // Numeric Types template <typename T> __forceinline T InternalConvert( const tr1::true_type &, const TypeValue& ) co nst { return NumberConvert<T>(); } template <typename T> __forceinline T& InternalConvert( const tr1::true_type &, const TypeReference& ) const { return *Cast<T>( ); } template <typename T> __forceinline T* InternalConvert( const tr1::true_type &, const TypePointer& ) const { return Cast<T>(); } }; } //namespace SqueakyClean

Anda mungkin juga menyukai