This shortcut tutorial will show you all basic information to use RTTR.
Class declaration
Suppose you have a class called node
which you want to introspect with RTTR.
#include <rttr/type>
namespace ns_3d
{
class node
{
public:
node(std::string name, node* parent = nullptr);
virtual ~node();
void set_name(const std::string& name);
const std::string& get_name() const;
std::vector<node*> get_children() const;
void set_visible(bool visible, bool cascade = true);
virtual void render();
private:
node* m_parent;
std::string m_name;
std::vector<node*> m_children;
};
}
The standard include file of rttr is: <rttr/type>
Remark the two added macros: RTTR_ENABLE() and RTTR_REGISTRATION_FRIEND. They are optional.
However, when you use class hierarchies you should add to every class: RTTR_ENABLE().
When you want to reflect private data of a class, add: RTTR_REGISTRATION_FRIEND.
Registration
Now comes the registration part, this is usually done in the corresponding source file.
#include <rttr/registration>
{
using namespace ns_3d;
(
)
.
property(
"name", &node::get_name, &node::set_name)
(
metadata(
"TOOL_TIP",
"Set the name of node.")
)
.property_readonly("children", &node::get_children)
.method("set_visible", &node::set_visible)
(
)
.
method(
"render", &node::render)
;
}
The standard include file for registration types in rttr is: <rttr/registration>
Include this file only when you want to register something. The registration class is here the entry point. This registration process creates internally wrapper classes, which store for example function pointers or object pointers of the specific class. For these pointers you have to provide the data manually.
Yeah, and that's it. Now you can use RTTR to retrieve this information.
Basic usage
#include <rttr/type>
#include <iostream>
int main(int argc, char *argv[])
{
prop.
set_value(var, std::string(
"A New Name"));
std::cout << prop.get_value(var).to_string() << "\n";
std::cout << "MetaData TOOL_TIP: " << prop.get_metadata("TOOL_TIP").to_string() << "\n";
std::cout << std::boolalpha <<
"invoke of method 'set_visible' was successfully: " << ret.
is_valid() <<
"\n\n";
std::cout << "'node' properties:" << "\n";
{
std::cout << " name: " << prop.get_name() << "\n";
std::cout << " type: " << prop.get_type().get_name() << "\n";
}
std::cout << "\n";
std::cout << "'node' methods:" << "\n";
{
std::cout <<
" name: " << meth.
get_name();
{
std::cout << " param " << info.get_index() << ": name: "<< info.get_name() << "\n";
}
}
return 0;
}
Remark, that there is actual no include of node.h
. See the output below:
Output
class std::shared_ptr<class ns_3d::node>
A New Name
MetaData TOOL_TIP: Set the name of node.
invoke of method 'set_visible' was successfully: true
'node' properties:
name: name
type: std::string
name: parent
type: ns_3d::node*
name: children
type: class std::vector<class ns_3d::node *,class std::allocator<class ns_3d::node *> >
'node' methods:
name: set_visible signature: set_visible( bool, bool )
param 0: name: visible
param 1: name: cascade
name: render signature: render( )
Derived classes
Suppose you create now from node
a derived class called mesh
.
#include <rttr/type>
class mesh : public node
{
public:
static std::shared_ptr<mesh> create_mesh(std::string file_name);
virtual void render();
enum class render_mode
{
POINTS,
WIREFRAME,
SOLID
};
void set_render_mode(render_mode mode);
render_mode get_render_mode() const;
private:
mesh(std::string name, node* parent = nullptr);
};
Now you put in RTTR_ENABLE() the name of the base class, in this case: node
.
Registration part
{
using namespace ns_3d;
.property("render_mode", &mesh::get_render_mode, &mesh::set_render_mode)
.enumeration<mesh::render_mode>("ns_3d::render_mode")
(
value(
"POINTS", mesh::render_mode::POINTS),
value(
"WIREFRAME", mesh::render_mode::WIREFRAME),
value(
"SOLID", mesh::render_mode::SOLID)
);
}
Remark that it is not necessary to register again the render()
method.
Basic Usage
#include <rttr/type>
#include <iostream>
#include "mesh.h"
int main(int argc, char *argv[])
{
std::shared_ptr<ns_3d::node> obj = ns_3d::mesh::create_mesh("House.obj");
std::cout << type::get(obj).get_name() << "\n";
std::cout << type::get(obj).get_wrapped_type().get_name() << "\n";
std::cout << type::get(*obj.get()).get_name() << "\n";
type t = type::get(*obj.get());
std::cout << "\n";
std::cout << "'mesh' properties:" << "\n";
for (auto& prop : t.get_properties())
{
std::cout <<
" name: " << prop.
get_name() <<
"\n";
std::cout << " type: " << prop.get_type().get_name() << "\n";
}
property prop = t.get_property("render_mode");
bool ret = prop.set_value(obj, ns_3d::mesh::render_mode::SOLID);
std::cout << "\n";
method meth = t.get_method("render");
std::shared_ptr<ns_3d::mesh> obj_derived = std::dynamic_pointer_cast<ns_3d::mesh>(obj);
variant var = meth.invoke(obj_derived);
std::cout << std::boolalpha <<
"invoke of method 'render' was successfully: " << var.
is_valid() <<
"\n";
}
See the output below:
Output
class std::shared_ptr<class ns_3d::node>
ns_3d::node*
ns_3d::mesh
'mesh' properties:
name: name
type: std::string
name: parent
type: ns_3d::node*
name: children
type: class std::vector<class ns_3d::node *,class std::allocator<class ns_3d::node *> >
name: render_mode
type: ns_3d::render_mode
ns_3d::node
invoke of method 'render' was successfully: true
That's it.
However, in order to see all the possibilities of RTTR, it is recommend to go through the in-depth tutorial: Start Tutorial