Engine Type System
Akin to C++ RTTI (though more thorough in depth), the engine type system provides a reflection layer that can be used to query type properties at run-time.
Classes:
Template for class type infos.
Template for function type infos.
Engine Type Traits
Type traits allow to access the static properties of a type at compile-time.
This is primarily useful for templating in order to make decisions based on static typing.
TYPE()
Return the type info for the given engine type.
T(x) typename < x >::ValueType
Defines
_DECLARE_BITFIELD(type) ( type ) \ template<> \ struct < type > : public < type > {};
_DECLARE_BITFIELD_R(type) ( type ) \ template<> \ struct < type > : public < type > {};
_DECLARE_ENUM(type) ( type ) \ template<> \ struct < type > : public < type > {};
_DECLARE_ENUM_R(type) ( type ) \ template<> \ struct < type > : public < type > {};
_DECLARE_PRIMITIVE(type) ( type ) \ template<> \ struct < type > : public < type > {};
_DECLARE_PRIMITIVE_R(type) ( type ) \ template<> \ struct < type > : public < type > {};
_DECLARE_STRUCT(type) ( type ) \ template<> \ struct < type > : public < type > {};
_DECLARE_STRUCT_R(type) ( type ) \ template<> \ struct < type > : public < type > {};
_DECLARE_TYPE(type) template<> * < type >(); \ template<> struct < type > { \ & operator()() { \ return *static_cast< * >( \ const_cast< * >( ( < type >() ) ) \ ); \ } \ };
_DECLARE_TYPE_R(type) template<> * < type >(); \ template<> struct < type > { \ & operator()() { \ return *reinterpret_cast< * >( \ const_cast< * >( ( < type >() ) ) \ ); \ } \ };
_END_IMPLEMENT_BITFIELD() }; \ static _sEnumTable( sizeof( _sEnums ) / sizeof( _sEnums[ 0 ] ), _sEnums ); \ < BitfieldType > gsTypeInfo( _sBitfieldName, &_sScope, , _sDoc, &_sEnumTable ); \ } }
_END_IMPLEMENT_ENUM() }; \ static _sEnumTable( sizeof( _sEnums ) / sizeof( _sEnums[ 0 ] ), _sEnums ); \ < EnumType > gsTypeInfo( _sEnumName, &_sScope, , _sDoc, &_sEnumTable ); \ } }
_END_IMPLEMENT_STRUCT() { } \ }; \ static _sFieldTable( sizeof( _sFields ) / sizeof( _sFields[ 0 ] ) - 1, _sFields ); \ < StructType > gsTypeInfo( _sStructName, &_sScope, _sDoc, &_sFieldTable ); \ } }
_FIELD(fieldName, exportName, numElements, doc) { #exportName, doc, numElements, ( ( ( ThisType* ) 16 )->fieldName ), ()( fieldName ) }
_FIELD_AS(type, fieldName, exportName, numElements, doc) { #exportName, doc, numElements, ( *( ( type* ) &( ( ThisType* ) 16 )->fieldName ) ), ()( fieldName ) }
_IMPLEMENT_BITFIELD(type, exportName, scope, doc) namespace { namespace _ ## exportName { \ extern < type > gsTypeInfo; \ } } \ ( type, exportName ); \ namespace { namespace _ ## exportName { \ typedef type BitfieldType; \ static char* _sBitfieldName = #exportName; \ static char* _sDoc = doc; \ static & _sScope = < scope >()(); \ static _sEnums[] = {
_IMPLEMENT_ENUM(type, exportName, scope, doc) namespace { namespace _ ## exportName { \ typedef type EnumType; \ extern < EnumType > gsTypeInfo; \ } } \ ( type, exportName ); \ namespace { namespace _ ## exportName { \ static char* _sEnumName = #exportName; \ static char* _sDoc = doc; \ static & _sScope = < scope >()(); \ static _sEnums[] = {
_IMPLEMENT_PRIMITIVE(type, exportName, scope, doc) namespace { namespace _ ## exportName { \ static < type > gsTypeInfo( #exportName, &< scope >()(), , doc ); \ } } \ ( type, exportName )
_IMPLEMENT_STRUCT(type, exportName, scope, doc) namespace { namespace _ ## exportName { \ extern < type > gsTypeInfo; \ } } \ ( type, exportName ); \ namespace { namespace _ ## exportName { \ typedef type StructType; \ typedef StructType ThisType; \ static char* _sStructName = #exportName; \ static char* _sDoc = doc; \ static & _sScope = < scope >()(); \ static _sFields[] = {
_IMPLEMENT_TYPE(type, exportName) template<> \ * < type >() \ { \ return &_ ## exportName::gsTypeInfo; \ }
ConsoleDocClass(className, doc) template<> char* < className, className::_ClassBase >::smDocString = doc;
DECLARE_BITFIELD(type) ( type )
DECLARE_BITFIELD_R(type) ( type )
DECLARE_ENUM(type) ( type )
DECLARE_ENUM_R(type) ( type )
DECLARE_PRIMITIVE(type) ( type )
DECLARE_PRIMITIVE_R(type) ( type )
DECLARE_SCOPE(name) struct name { \ static __engineExportScopeInst; \ static & __engineExportScope() { return __engineExportScopeInst; } \ };
DECLARE_STRUCT(type) ( type )
DECLARE_STRUCT_R(type) ( type )
FIELD(fieldName, exportName, numElements, doc) (fieldName, exportName, numElements, doc),
FIELD_AS(type, fieldName, exportName, numElements, doc) (type, fieldName, exportName, numElements, doc),
FIELDOFFSET(fieldName) ( ( ( char* ) &( ( ( ThisType* ) 16 )->fieldName ) ) - 16 )
IMPLEMENT_BITFIELD(type, exportName, scope, doc) ( type, exportName, scope, doc )
IMPLEMENT_ENUM(type, exportName, scope, doc) ( type, exportName, scope, doc )
IMPLEMENT_PRIMITIVE(type, exportName, scope, doc) ( type, exportName, scope, doc )
IMPLEMENT_SCOPE(name, exportName, scope, doc) name::__engineExportScopeInst( #exportName, &< scope >()(), doc );
IMPLEMENT_STRUCT(type, exportName, scope, doc) ( type, exportName, scope, doc )
Detailed Description
Akin to C++ RTTI (though more thorough in depth), the engine type system provides a reflection layer that can be used to query type properties at run-time.
Type Kinds
Engine types are segregated into kinds. A kind is to a type what a type is to a value, i.e. a value is an instance of a type whereas a type is an instance of a kind.
Just as values share behavior through types, types share behavior through kinds.
The following kinds are defined:
- Primitive
An atomic piece of data like an int, float, etc.
- Enums
- Bitfields
A bitwise combination of enumeration values.
- Functions
- Structs
A structured piece of data like a Point3F or MatrixF. Unlike class instances, structs are directly stored in the memory of their owner. Also, structs don't allow inheritance.
- Classes
Subtyping of Engine Types
At the moment, the type system is not unified such that all types are implicitly subtypes to a single root type. This may change in the future.
Default Construction
All engine types must be default-constructible, i.e. a parameter-less construction of a value of any type in the engine must be successful. Class and struct types are affected the most by this. Classes and structs may provide non-default constructors but they must provide a default construction routine that always succeeds.
Engine Type Traits
Type traits allow to access the static properties of a type at compile-time.
This is primarily useful for templating in order to make decisions based on static typing.
TYPE()
Return the type info for the given engine type.
TYPE(const T & )
Return the type info for the static type of the given variable.
const EngineTypeInfo *const TYPEINFO
const EngineTypeInfo *const TYPEINFO
const EngineTypeInfo *const TYPEINFO
const EngineTypeInfo *const TYPEINFO
const EngineTypeInfo *const TYPEINFO
const EngineTypeInfo *const TYPEINFO
T(x) typename < x >::ValueType
Defines
_DECLARE_BITFIELD(type) ( type ) \ template<> \ struct < type > : public < type > {};
_DECLARE_BITFIELD_R(type) ( type ) \ template<> \ struct < type > : public < type > {};
_DECLARE_ENUM(type) ( type ) \ template<> \ struct < type > : public < type > {};
_DECLARE_ENUM_R(type) ( type ) \ template<> \ struct < type > : public < type > {};
_DECLARE_PRIMITIVE(type) ( type ) \ template<> \ struct < type > : public < type > {};
_DECLARE_PRIMITIVE_R(type) ( type ) \ template<> \ struct < type > : public < type > {};
_DECLARE_STRUCT(type) ( type ) \ template<> \ struct < type > : public < type > {};
_DECLARE_STRUCT_R(type) ( type ) \ template<> \ struct < type > : public < type > {};
_DECLARE_TYPE(type) template<> * < type >(); \ template<> struct < type > { \ & operator()() { \ return *static_cast< * >( \ const_cast< * >( ( < type >() ) ) \ ); \ } \ };
_DECLARE_TYPE_R(type) template<> * < type >(); \ template<> struct < type > { \ & operator()() { \ return *reinterpret_cast< * >( \ const_cast< * >( ( < type >() ) ) \ ); \ } \ };
_END_IMPLEMENT_BITFIELD() }; \ static _sEnumTable( sizeof( _sEnums ) / sizeof( _sEnums[ 0 ] ), _sEnums ); \ < BitfieldType > gsTypeInfo( _sBitfieldName, &_sScope, , _sDoc, &_sEnumTable ); \ } }
_END_IMPLEMENT_ENUM() }; \ static _sEnumTable( sizeof( _sEnums ) / sizeof( _sEnums[ 0 ] ), _sEnums ); \ < EnumType > gsTypeInfo( _sEnumName, &_sScope, , _sDoc, &_sEnumTable ); \ } }
_END_IMPLEMENT_STRUCT() { } \ }; \ static _sFieldTable( sizeof( _sFields ) / sizeof( _sFields[ 0 ] ) - 1, _sFields ); \ < StructType > gsTypeInfo( _sStructName, &_sScope, _sDoc, &_sFieldTable ); \ } }
_FIELD(fieldName, exportName, numElements, doc) { #exportName, doc, numElements, ( ( ( ThisType* ) 16 )->fieldName ), ()( fieldName ) }
_FIELD_AS(type, fieldName, exportName, numElements, doc) { #exportName, doc, numElements, ( *( ( type* ) &( ( ThisType* ) 16 )->fieldName ) ), ()( fieldName ) }
_IMPLEMENT_BITFIELD(type, exportName, scope, doc) namespace { namespace _ ## exportName { \ extern < type > gsTypeInfo; \ } } \ ( type, exportName ); \ namespace { namespace _ ## exportName { \ typedef type BitfieldType; \ static char* _sBitfieldName = #exportName; \ static char* _sDoc = doc; \ static & _sScope = < scope >()(); \ static _sEnums[] = {
_IMPLEMENT_ENUM(type, exportName, scope, doc) namespace { namespace _ ## exportName { \ typedef type EnumType; \ extern < EnumType > gsTypeInfo; \ } } \ ( type, exportName ); \ namespace { namespace _ ## exportName { \ static char* _sEnumName = #exportName; \ static char* _sDoc = doc; \ static & _sScope = < scope >()(); \ static _sEnums[] = {
_IMPLEMENT_PRIMITIVE(type, exportName, scope, doc) namespace { namespace _ ## exportName { \ static < type > gsTypeInfo( #exportName, &< scope >()(), , doc ); \ } } \ ( type, exportName )
_IMPLEMENT_STRUCT(type, exportName, scope, doc) namespace { namespace _ ## exportName { \ extern < type > gsTypeInfo; \ } } \ ( type, exportName ); \ namespace { namespace _ ## exportName { \ typedef type StructType; \ typedef StructType ThisType; \ static char* _sStructName = #exportName; \ static char* _sDoc = doc; \ static & _sScope = < scope >()(); \ static _sFields[] = {
_IMPLEMENT_TYPE(type, exportName) template<> \ * < type >() \ { \ return &_ ## exportName::gsTypeInfo; \ }
ConsoleDocClass(className, doc) template<> char* < className, className::_ClassBase >::smDocString = doc;
DECLARE_BITFIELD(type) ( type )
DECLARE_BITFIELD_R(type) ( type )
DECLARE_ENUM(type) ( type )
DECLARE_ENUM_R(type) ( type )
DECLARE_PRIMITIVE(type) ( type )
DECLARE_PRIMITIVE_R(type) ( type )
DECLARE_SCOPE(name) struct name { \ static __engineExportScopeInst; \ static & __engineExportScope() { return __engineExportScopeInst; } \ };
DECLARE_STRUCT(type) ( type )
DECLARE_STRUCT_R(type) ( type )
END_IMPLEMENT_BITFIELD()
END_IMPLEMENT_ENUM()
END_IMPLEMENT_STRUCT()
FIELD(fieldName, exportName, numElements, doc) (fieldName, exportName, numElements, doc),
FIELD_AS(type, fieldName, exportName, numElements, doc) (type, fieldName, exportName, numElements, doc),
FIELDOFFSET(fieldName) ( ( ( char* ) &( ( ( ThisType* ) 16 )->fieldName ) ) - 16 )
IMPLEMENT_BITFIELD(type, exportName, scope, doc) ( type, exportName, scope, doc )
IMPLEMENT_ENUM(type, exportName, scope, doc) ( type, exportName, scope, doc )
IMPLEMENT_PRIMITIVE(type, exportName, scope, doc) ( type, exportName, scope, doc )
IMPLEMENT_SCOPE(name, exportName, scope, doc) name::__engineExportScopeInst( #exportName, &< scope >()(), doc );
IMPLEMENT_STRUCT(type, exportName, scope, doc) ( type, exportName, scope, doc )