New Release of RTTR (0.9.5)

Axel Menzel Comments releases

This update of RTTR marks a big milestone in its development. I dug basically the whole codebase, under the surface and above. I learned it the hard way what the 80-20 rule means. For the last 20%, you have to invest 80% of the development time.

Anyway, what changes does this release include?

No more RTTR_DECLARE_TYPE()

This is biggest change, it is not necessary anymore to register types with the macro RTTR_DECLARE_TYPE. I solved this by retrieving the string literals of the type via compiler specific macros, like __PRETTY_FUNCTION__. That means internally RTTR still does not depend on rtti, which can be a requirement on certain hardware.

Registration Process

The second big change was the registration process of the reflection information. I developed a completely new approach, which I find more easier and future-proof. The usage of the variadic templates was quite handy, without it would not be possible.

Take a look at following snippet:

#include <rttr/registration>
using namespace rttr;

struct MyStruct { MyStruct(int value = 23) {};  };

RTTR_REGISTRATION
{
    registration::class_<MyStruct>("MyStruct")
        .constructor<int>()
        (
            policy::ctor::as_std_shared_ptr,
            default_arguments(23),
            metadata("label", "some text")
        );
}

The key part here is, after you close the first parenthesis .constructor<int>(), you can open a second context with operator () for the previously registered item to add additional information. The order of the provided information is up to you.

Providing Metadata

void my_func() {}
enum class meta_info { label, scriptable };

RTTR_REGISTRATION
{
    registration::method("my_func", &my_func)
    (
        metadata(meta_info::label, "This is a simple label"),
        metadata(meta_info::scriptable, false),
        metadata("Description", "This is a simple description")
    );
}

You want to provide metadata, no problem, use the function metadata(variant key, variant value) in the second context. This reduces also the hassle with the parenthesis of the std::initializer_list in the 0.9.0 version. As key, you can now also use a variant.

Providing Default Arguments:

void my_function(int a, bool b, const std::string& text, const int* ptr);

RTTR_REGISTRATION
{
    registration::method("my_function", &my_function)   
    (
        default_arguments(true, std::string("default text"), nullptr)
    );
}

You want to register functions which has default arguments? Also no big deal, provide the necessary information in the second context. Just make sure the given arguments must match the signature from the starting position to the right most argument.

Providing Parameter Names

void set_window_geometry(const char* name, int w, int h) {...}

RTTR_REGISTRATION
{
     registration::method("set_window_geometry", &set_window_geometry)
     (
         parameter_names("window name", "width", "height")
     );
}

It is now possible to provide additional meta information for arguments of a method or constructor. As first step you can provide the human readable names of the arguments. This information can be retrieved later via the new class paramter_info.

Providing Access specifier

struct Foo { protected: void func() {}  RTTR_REGISTRATION_FRIEND };

RTTR_REGISTRATION
{
    registration::class_<Foo>("Foo")
        .method("func", &Foo::func, registration::protected_access);
}

The access specifier of a member item can now be forwarded during the registration process. In the next release, I will provide an API for retrieving only public or private items.

Providing Policies

int my_func() { return 42; }
RTTR_REGISTRATION
{
    registration::method("my_func", &my_func)
    (
        policy::meth::discard_return
    );
}

The old policies are still supported and some new policies for constructors were added. Another change is, that the policies are now grouped under the policy class for easier usage.

Variant

Other changes involves the variant class. It has get an optimization for small data types (e.g. double) to avoid dynamic memory allocation with new. More over, the variant class supports now the operators == and <.

The variant_array class has been replaced by variant_array_view. This class will not copy any memory, it will be just a view into the variant, when it is an array.

Invoke with wrapped types

Methods and properties can now be invoked also when they are wrapped inside a wrapper type, like std::shared_ptr.

const type t = type::get_by_name("MyStruct");
variant var = t.create();
const std::shared_ptr<MyStruct>& obj = var.get_value<std::shared_ptr<MyStruct>>();

method meth = t.get_method("func");

method.invoke(obj, 42);         // successful invoke
method.invoke(obj.get(), 42);   // successful invoke
method.invoke(*obj.get(), 42);  // successful invoke

// or use the variant
method.invoke(var, 42);         // successful invoke

Misc Changes

The tutorial section and a a big part of the documentation were adjusted. I also switched from mercurial to git as DVCS and uploaded the project to GitHub. Like you can see and read I also created a small website, as a central contact point for the whole project. I used therefore Grav, checked it out.

Struggles

I have fought several battles with the VS 2013 compiler, to get all the TMP code running. But thanks to the very good support of the Visual Studio Compiler/Library team, I get my code running (with workarounds of course). A lot of them are not needed anymore for VS 2015, but up to the 1.0 release I will still support VS 2013.

Benchmarks

I used nonius for benchmarking certain API calls of the library. Here are some sample output, generated with VS2013 win64 on a Core2Quad CPU @3Ghz.

These benchmarks are as optional targets included in RTTR source code repository, so you can build and run them yourself.

What is on the roadmap till 1.0?

  • Make the registration part thread safe; I have an idea how to do this without any locks or atomics, but it is quite a big change in the registration database and I am not sure yet about its performance impact
  • provide error messages when something went wrong; RTTR does not provide exceptions, however to get some kind of information about errors it would be nice to get some message in the console
  • add CI for the github project
  • provide more unit tests (100% code coverage would be really nice)
  • maybe provide implicit conversion between raw data types during invoke of methods (e.g. int to double)
  • maybe some minor API clean ups
  • your feature request?

Roadmap ahead of 1.x

  • provide some kind of plugin infrastructure for serialization and script binding
  • add some standard serialization plugins, e.g. JSON
  • ...

You find the source code and binaries in the download section or also on GitHub. I hope you enjoy this release. When you have any questions or inquiries, you can drop me a line at info@rttr.org or contact me via the website.

That's all for the moment. Happy holidays!

Over and out.


Blog Comments powered by Disqus.