Giter VIP home page Giter VIP logo

libertti's Introduction

Liberate your C++ with reflection!



LibeRTTI is a header only and dependency-free library which provides type data for your (and selected built-in) c++ types. The minimal requirement is C++14.

Features ๐Ÿ—ฝ

Feature Description
Hierarchy based Every registered type gets its unique nested type class, e.g if you have a class A then it's type class will be A::Type. These type classes create a hierarchy based on their original classes hierarchy. So for instance, if class A : public B, then class A::Type : class B::Type. Also, all type classes are virtual, even if their original classes are not. It allows you to take advantage of polymorphic features like having a function parameter of type const A::Type& and passing the children types of A as arguments. rtti:Type is the root class for all types classes.
Namespaces and nested types friendly Types within namespaces and other types are fully supported.
"Super" keyword A well known feature from other languages. The Super keyword refers to the parent class of your class.
Instantiating/Destroying/Copying without knowing true type Type classes are able to instantiate, destroy or copy raw memory which contains the types they represent.
Move without knowing true type (Optional) Same as above but with the move operation. It forces all registered types to be movable. It might be disabled by defining RTTI_REQUIRE_MOVE_CTOR 0 before including the LibeRTTI header.
Recognizing object's true type You can get the true type of your polymorphic class instance.
Types register LibeRTTI gives you access to all registered types.
Properties and Methods Types might keep data about the their member variables and methods to make them accessible in runtime.
Metadata Types and properties can store additional string-based metadata.
Unique and persistent IDs All registered types and their properties get unique IDs which persist between executions unless the name of the type/property changes.
Primitive Types All primitive types are registered out of the box.
Enums Custom enum classes can also be registered.
Pointer Types Pointer types are registered lazily at runtime when the need for them arrises. You're not limited by the amount of indirections (properties like float***** are allowed). Pointer types follow their original classes hierarchy. I.e PointerType<B> inherits from PointerType<A> if B also inherits from A.
Runtime Types You can compose completely new type with selected properties in runtime. Such types can still inherit from other types and preserve hierarchy of classes.
std::
shared_ptr,
unique_ptr,
vector,
unordered_set,
unordered_map,
pair,
string
Types (Optional)
All these types are registered out of the box and might be disabled using config defines:
RTTI_CFG_CREATE_STD_SHAREDPTR_TYPE 0,
RTTI_CFG_CREATE_STD_UNIQUEPTR_TYPE 0,
RTTI_CFG_CREATE_STD_VECTOR_TYPE 0,
RTTI_CFG_CREATE_STD_SET_TYPE 0,
RTTI_CFG_CREATE_STD_MAP_TYPE 0,
RTTI_CFG_CREATE_STD_PAIR_TYPE 0,
RTTI_CFG_CREATE_STD_STRING_TYPE 0
โ€

Demo ๐Ÿ—ฝ

More examples can be found in Tests or Forge project source code.

// .h
struct BaseStruct
{
  RTTI_DECLARE_STRUCT( BaseStruct );
};

struct MyStruct : public BaseStruct
{
  RTTI_DECLARE_STRUCT( MyStruct, BaseStruct );

  float myFloat;
  MyStruct* myPtr;
  BaseStruct myCustomInstance;

  MyStruct* Foo( Float input )
  {
    myFloat = input;
    return this;
  }
}

// .cpp
RTTI_IMPLEMENT_TYPE( BaseStruct );
RTTI_IMPLEMENT_TYPE( MyStruct,
  RTTI_REGISTER_PROPERTY( myFloat,
    RTTI_ADD_METADATA( MyCustomMetadata, 321 );
  );
  RTTI_REGISTER_PROPERTY( myPtr );
  RTTI_REGISTER_PROPERTY( myCustomInstance );
  RTTI_REGISTER_METHOD( Foo );
  RTTI_ADD_METADATA( MyCustomMetadata );
  RTTI_ADD_METADATA( MyCustomMetadataWithValue, 123 );
);

static_assert( MyStruct::GetTypeStatic().InheritsFrom< BaseStruct::Type > );

void Func( void* rawInstance, const rtti::Type& type )
{
  if( type.IsA< MyType >() )
  {
    const MyStruct::Type& myType = static_cast< const MyStruct::Type& >( type );

    // Accessing properties
    const rtti::Property* floatProperty = myType.FindProperty( "myFloat" );
    if ( floatProperty->GetType().IsA< float >() )
    {
      floatProperty->GetValue< float >( rawInstance ) = 3.14f;
    }
    myType.FindProperty( "myCustomInstance" )->GetValue< BaseStruct >( rawInstance ) = BaseStruct();

    // Calling methods
    MyType* fooResult = nullptr;
    float arg = 3.14f;
    myType.FindMethod( "Foo" )->Call( /*instance*/ rawInstance, /*args*/ &arg, /*outcome*/ &fooResult );

    // Accessing metadata
    if ( myType.HasMetadata( "MyCustomMetadata ) )
    {
      // type contains provided metadata
    }
    if (const std::string* metadataValue = myType.GetMetadataValue( "MyCustomMetadataWithValue" )
    {
      *metadataValue == "123 // true
    }
    if( myType.FindProperty( "myFloat" )->HasMetadata( "MyCustomMetadata ") )
    {
      // property contains provided metadata
    }
  }
}

Usage ๐Ÿ—ฝ

Registering your type requires 2 steps.

1. Declare type

Put one of the following macros into your type's body.

Type Macro
Regular, non virtual class
 RTTI_DECLARE_CLASS( <class_name>, <parent_name_with_namespace> (optional) ) 
Virtual class
 RTTI_DECLARE_POLYMORPHIC_CLASS( <class_name>, <parent_name_with_namespace> (optional) ) 
Abstract class
 RTTI_DECLARE_ABSTRACT_CLASS( <class_name>, <parent_name_with_namespace> (optional) ) 
Struct
 RTTI_DECLARE_STRUCT( <struct_name>, <parent_name_with_namespace> (optional) ) 

2. Implement type

Structs and Classes

Put the following macro in .cpp file.

RTTI_IMPLEMENT_TYPE( <class_name_with_namespace>, <properties/methods/metadata_registration_macros... (optional)> );

To register property of your type use:

RTTI_REGISTER_PROPERTY( <property_name>, <metadata_macros... (optional)...> );

For methods use:

RTTI_REGISTER_METHOD( <method_name> );

To add type or property metadata:

RTTI_ADD_METADATA( <key>, <value (optional)> );

and put it in RTTI_IMPLEMENT_TYPE (for types) or RTTI_REGISTER_PROPERTY (for properties) macro.


Enums

To register your custom enum put the following macro in .cpp file.

RTTI_DECLARE_AND_IMPLEMENT_ENUM( <enum_name_with_namespace>, <enum_members...> )

To register enum's members use:

RTTI_REGISTER_ENUM_MEMBER( <member_name> );

and put it in RTTI_DECLARE_AND_IMPLEMENT_ENUM macro.

libertti's People

Contributors

wuszt avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.