For registering classes in RTTR you use a class called registration::class_<T>. Its name is supposed to resemble the C++ keyword, to make it look more intuitive. It has member functions for register constructors, properties, methods and enums. These functions have the same interface and work in the same way like register the global symbols. Every call to these member functions, will return bind object, in order to chain more registration calls.
Let's start with a simple example. Consider the following C++ class:
The registration process is now done at global scope in the cpp file.
This will register the class test_class
with a constructor that takes an integer as argument, a member function with the name print_value
and a property called value
.
The property name has to be unique for this class type, but derived classes can register another property with the same name again. Member functions can be overloaded, so a method can be registered with an already existing name multiple times. However when there exist a method with the same name and signature, then this function will not be registered and discarded.
Overloaded member functions
In order to register a overloaded member function, you have to disambiguate the member function pointer you pass to method. Therefore a helper function can be used: select_overload<T>(T (ClassType::*func))
Here's an example illustrating this:
The last function is a overloaded const function, use therefore the select_const() function.
Register constructor
RTTR allows your to register constructors for classes. Because C++ doesn't allow to retrieve the member function pointer of a constructor you have to explicit specify all data types of a constructor.
Consider following class with three constructors:
For registering three Foo
constructors you now have to specify every parameter as template parameter in the member function constructor(). As second option, it is possible to register a static function as constructor. In order to do this, just forward the function pointer.
When a constructor is registered a destructor is registered automatically. The used default policy for creating an instance is policy::ctor::as_object.
Register class properties
Register a public property can be easily done, consider following class:
This class is registered like this:
With the property() member function you will register the member variable Foo::value
with read and write access.
Read Only Properties
When you want a register a property with read-only
access, then this is also possible with property_readonly() member function.
Private Properties
When you have a class and the property is declared in private scope, then you can still register this property when you insert the macro: RTTR_REGISTRATION_FRIEND inside the class.
This will make this class a friend to the registration system.
Getter Setter For Properties
You can also register getter and setter functions and make them look as if they were a public data member. Consider the following class:
This is the registration code:
This way, accessing the property will now call these functions, instead the property directly. Remark that the getter function needs the be const
.
The following sub sections will now show how to retrieve these informations for creating, invoking and setting properties of an instance of this class.
Access Level Of Class Members
With RTTR it is also possible to specify on of the three access modifiers during the registration.
The access level has to be specified as last argument in the corresponding class_ registration function. Use therefore one of the three static member variables in the registration class. This information can be retrieved at runtime for properties, methods or constructors. via the function get_access_level()
, which will return a enum value of type access_levels.
Create/destroy of classes
There are two options for creating/destroying a class.
- use just the type interface or
- retrieve a constructor and destructor object from the type class.
The objects which are constructed are created on the heap and stored as pointer in the variant object.
Invoke member functions
Invoking a member function works in the same way like invoking global function. The only difference is, that you have to provide the instance of the class.
The invoke function also except to use variants. So when you create the object via the type constructor you can use the returned variant to invoke a method:
It is possible to invoke a method, when the instance is wrapped inside a wrapper class, for example std::shared_ptr<T>
.
When you want to use RTTR with a custom wrapper type, you have provide a specialization of the class template wrapper_mapper<T>.
Set/Get property of a class
Properties can be also set and get in two steps:
In difference to the global properties, a valid type object and an instance (object) of the class is now needed to set and get the value. It doesn't matter in what hierarchy level the object is or if its a pointer, an object on the stack or wrapped inside a variant. RTTR will try to cast the given object to the class type where the property was registered to.