Question

Most mature C++ projects seem to have an own reflection and attribute system, i.e for defining attributes which can be accessed by string and are automatically serializable. At least many C++ projects I participated in seemed to reinvent the wheel.

Do you know any good open source libraries for C++ which support reflection and attribute containers, specifically:

  • Defining RTTI and attributes via macros
  • Accessing RTTI and attributes via code
  • Automatic serialisation of attributes
  • Listening to attribute modifications (e.g. OnValueChanged)
Was it helpful?

Solution

You could have a look at the two tools below. I've never used either of them, so I can't tell you how (im)practical they are.

XRTTI:

Xrtti is a tool and accompanying C++ library which extends the standard runtime type system of C++ to provide a much richer set of reflection information about classes and methods to manipulate these classes and their members.

OpenC++:

OpenC++ is C++ frontend library (lexer+parser+DOM/MOP) and source-to-source translator. OpenC++ enables development of C++ language tools, extensions, domain specific compiler optimizations and runtime metaobject protocols.

OTHER TIPS

This is what you get when C++ meets Reflection:

C++ meets Reflection

Whatever you choose, it'll probably have horrible macros, hard to debug code or weird build steps. I've seen one system automatically generate the serialisation code from DevStudio's PDB file.

Seriously though, for small projects, it'll be easier to write save/load functions (or use streaming operators). In fact, that might hold for big projects too - it's obvious what's going on and you'd usually need to change code anyway if the structure changes.

There is a new project providing reflection in C++ using a totally different approach: CAMP. https://github.com/tegesoft/camp

CAMP doesn't use a precompiler, the classes/properties/functions/... are declared manually using a syntax similar to boost.python or luabind. Of course, people can use a precompiler like gccxml or open-c++ to generate this declaration if they prefer.

It's based on pure C++ and boost headers only, and thanks to the power of template meta-programming it supports any kind of bindable entity (inheritance and strange constructors are not a problem, for example).

It is distributed under the MIT licence (previously LGPL).

I looked at these things for quite a while but they tend to be very heavy-handed. They might prevent you from using inheritance, or having strange constructors etc etc. In the end they ended up being too much of a burden instead of a convenience.

This approach for exposing members that I now use is quite lightweight and lets you explore a class for serialization or setting all fields called "x" to 0, for example. It's also statically determined so is very very fast. No layers of library code or code-gen to worry about messing with the build process. It generalises to hierarchies of nested types.

Set your editor up with some macros to automate writing some of these things.

struct point
{
     int x;
     int y;

     // add this to your classes
     template <typename Visitor>
     void visit(Visitor v)
     {
         v->visit(x, "x"); 
         v->visit(y, "y");
     }
};


/** Outputs any type to standard output in key=value format */
struct stdout_visitor
{
     template <typename T>
     void visit(const T& rhs)
     {
         rhs.visit(this);
     }

     template <typename Scalar>
     void visit (const Scalar& s, const char* name)
     {
          std::cout << name << " = " << s << " ";
     }
}

Looked at this for a while too. The current easiest solution seems to be BOOST_FUSION_ADAPT_STRUCT. Practically once you have a library/header you only need to add your struct fields into the BOOST_FUSION_ADAPT_STRUCT() macro, as the last segment of the code shows. Yes it has restrictions many other people have mentioned. And it does not support listeners directly.

The other promising solutions I looked into are

  • CAMP and XRTTI/gccxml, however both seem to be a hurdle to bring external tools dependency into your project.
  • Years ago I used perl c2ph/pstruct to dump the meta info from the output of gcc -gstabs, that is less intrusive but needs more work though it worked perfectly for me.

Regarding the boost/__cxa approach, once you figure out all the small details, adding/changing structs or fields is simple to maintain. we currently use it to build a custom types binding layer on top of dbus, to serialize the API and hide the transport/RPC details for a managed object service subsystem.

Not a general one but QT supports this via a meta compiler, and is GPL. My understanding from talking to the QT people was that this isn't possible with pure C++, hence the need for the moc.

This is a notorious weakness of the C++ language in general because the things that would need to be standardized to make reflection implementations portable and worthwhile aren't standard. Calling conventions, object layouts, and symbol mangling come to mind, but there are others as well.

The lack of direction from the standard means that compiler implementers will do some things differently, which means that very few people have the motivation to write a portable reflection library, which means that people who need reflection re-invent the wheel, but only just enough for what they need. This happens ad infinitum, and here we are.

Automatic introspection/reflection toolkit. Use meta compiler like Qt's and adding meta information directly into object files. Intuitive easy to use. No external dependencies. Even allow automatically reflect std::string and then use it in scripts. Please visit IDK

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top