Skip to content

ReflectionInCpp

djewsbury edited this page Mar 12, 2015 · 1 revision

#Reflection in C++

Some kind of reflection functionality is pretty useful to have for tools...

Imagine we have a POD native type containing properties and settings:

class ModelVisSettings
{
public:
    std::string _modelName;
    RenderCore::Techniques::CameraDesc _camera;
};

We want to automatically bind this object to a properties dialog in such a way that a user can change settings.

##Different types of reflection

There's a great thread on StackOverflow discussing some different possibilites. http://stackoverflow.com/questions/41453/how-can-i-add-reflection-to-a-c-application

Let's look at different options.

###Create a C++/CLI wrapper

A simple method would be to just create a wrapper class in C++/CLI with the same members. We can use the CLI annotations to add extra data to fields (such as what editor to use, etc). But we have to maintain 2 separate classes.

It's simple, it's fairly practical... But it's a little extra work.

###Build reflection data with external compiler

There seem to be a few tools that can parser C++ code and build a database of type information. That type information can be read during runtime.

This looks like a good tool:

This requires an extra compile step, and might impose restrictions on build tool optiosn.

###Reflection field data outside of the class

Using a system of macros and templates, we can manually add type data with C++. Here's an example: http://www.axelmenzel.de/projects/coding/rttr

RTTR_REFLECT
{
  class_<Mesh>()
    .constructor<>()
    .constructor<const std::string&>()
    .enumeration<E_TransformSpace>({{"TS_LOCAL", TS_LOCAL},
                                    {"TS_PARENT", TS_PARENT},
                                    {"TS_WORLD", TS_WORLD}})
    .property("pos", &Mesh::getPosition, &Mesh::setPosition)
    .method("setDirection", &Mesh::setDirection);
}

This creates a new class that contains static information describing the layout of another class.

###Reflection field data within a class

This is a common solution... We can implement some macros that add a table of reflection data with a class.

That StackOverflow page contains a pretty interesting implementing using variadic macros:

These macros separate the type name from the variable name, in a pretty neat and clean why:

#define REM(...) __VA_ARGS__
#define EAT(...)

// Retrieve the type
#define TYPEOF(x) DETAIL_TYPEOF(DETAIL_TYPEOF_PROBE x,)
#define DETAIL_TYPEOF(...) DETAIL_TYPEOF_HEAD(__VA_ARGS__)
#define DETAIL_TYPEOF_HEAD(x, ...) REM x
#define DETAIL_TYPEOF_PROBE(...) (__VA_ARGS__),
// Strip off the type
#define STRIP(x) EAT x
// Show the type without parenthesis
#define PAIR(x) REM x

This particular implementation looks pretty clean. But this style of implementation tends to involve more complex macros than reflection data outside of the class.

With this method, we need to change the actual implementation of the class we want to reflect. This means we can't add reflection data to classes in third party libraries.

###Using DLL export hacks

We can get some type information from the DLL exports table using __declspec(dllexport).

This would only give us methods (not members). By perhaps we can combine it with __declspec(property)?

It also means we have to fill up our dllexports table with information -- that could possibly be unsecure?

##So many options

So many options... The system of macros on the StackOverflow page looks really interesting.

But it may be that just creating a C++/CLI wrapper is just more practical in the long-run. Plus, the wrapper allows us to add annotation data (or make any other transformations to the data as it passes through the UI).

If we need reflection data for purposes other than binding to the UI, then perhaps a good built-in reflection solution would make sense.

Or if we really wanted to be able to bind arbitrary C++ types of the UI, we could do that with reflection. But I wonder how useful that would really be.