views:

7963

answers:

16

I'd like to be able to introspect a C++ class for its name, contents (i.e. members and their types) etc. I'm talking native C++ here, not managed C++, which has reflection. I realise C++ supplies some limited information using RTTI. Which additional libraries (or other techniques) could supply this information?

+23  A: 

And I would love a pony, but ponies aren't free. :-p

http://en.wikibooks.org/wiki/C%2B%2B_Programming/RTTI is what you're going to get. Reflection like you're thinking about -- fully descriptive metadata available at runtime -- just doesn't exist for C++ by default.

Brad Wilson
I second Brad. C++ templates can be rather powerful, and there is a wealth of experience around various 'reflection' type behaviors, such at boost 'any' library, type traits, C++ RTTI etc. that can solve many of the problems reflection is solved for.So Nick, what's your goal here?
Aaron
Upvote for the ponies remark! I'd upvote twice, as your answer also deserves it, but sadly I get only one, so ponies win. :-)
Franci Penov
I don't really get why this is a clever response. I've already said I'd like references to libraries etc to implement this. The reflection/introspection is for various system to allow script access, serialisation etc.
Nick
@Nick: He already answered that. It can't be done, the data does not exist, and therefore, no library is able to implement it for you.
jalf
+5  A: 

What are you trying to do with reflection?
You can use the Boost type traits and typeof libraries as a limited form of compile-time reflection. That is, you can inspect and modify the basic properties of a type passed to a template.

Ferruccio
+1  A: 

The two reflection-like solutions I know of from my C++ days are:

1) Use RTTI, which will provide a bootstrap for you to build your reflection-like behaviour, if you are able to get all your classes to derive from an 'object' base class. That class could provide some methods like GetMethod, GetBaseClass etc. As for how those methods work you will need to manually add some macros to decorate your types, which behind the scenes create metadata in the type to provide answers to GetMethods etc.

2) Another option, if you have access to the compiler objects is to use the DIA SDK. If I remember correctly this lets you open pdbs, which should contain metadata for your C++ types. It might be enough to do what you need. This page shows how you can get all base types of a class for example.

Both these solution are a bit ugly though! There is nothing like a bit of C++ to make you appreciate the luxuries of C#.

Good Luck.

A: 

The information simply does not exist at runtime. You will have to devise the entire scheme yourself.

Good luck with that.

DrPizza
+6  A: 

I would recommend using Qt.

There is an open-source licence as well as a commercial licence.

Jérôme
I looked at this but it uses macros and the source code needs parsing to generate the meta-data code. I'd like to avoid this extra step. I'd prefer to use a C++ library or simple macros. Thanks for the idea though.
Nick
QT, or another library implementing a similar approach is the best you're going to get
jalf
Pay at compile time or pay at runtime - either way you are paying!
Martin Beckett
+9  A: 

RTTI doesn't exist for C++.

This is simply wrong. Actually, the very term “RTTI” was coined by the C++ standard. On the other hand, RTTI doesn't go very far in implementing reflection.

Konrad Rudolph
A: 

A simple way is to use de dynamic_cast<> operator which, when assigned to an wrong type, returns NULL, so you can upcast to a base concrete class in an easy way, checking the value of the pointer, if it is not NULL, the cast was done, and you got the type of the object.

But this is just a simple solution, and it only provides the type of the objects, you cannot ask what methods it has, like in Java. If you need an advanced solution, there are some frameworks to choose from.

lurks
+2  A: 

You need to look at what you are trying to do, and if RTTI will satisfy your requirements. I've implemented by own pseudo-reflection for very specific purposed. One was to be able to flexibly configure what was output from a simulation. It required adding some boilerplate to the classes that would be output:

namespace {
  static bool b2 = Filter::Filterable<const MyObj>::Register("MyObject");
} 

bool MyObj::BuildMap()
{
  Filterable<const OutputDisease>::AddAccess("time", &MyObj::time);
  Filterable<const OutputDisease>::AddAccess("person", &MyObj::id);
  return true;
}

The first call adds this object to the filtering system, which calls the BuildMap() method to figure out what methods are available.

Then in the config file, you can do something like this:

FILTER-OUTPUT-OBJECT   MyObject
FILTER-OUTPUT-FILENAME file.txt
FILTER-CLAUSE-1        person == 1773
FILTER-CLAUSE-2        time > 2000

Through some template magic involving boost, this get translated into a series of method calls at runtime (when the config file is read), so its fairly efficient. I wouldn't recommend doing this unless you really need to, but when you do, you can do some really cool stuff.

KeithB
+2  A: 

I think you might find interesting the article "Using Templates for Reflection in C++" by Dominic Filion. It is in section 1.4 of Game Programming Gems 5. Unfortunately I dont have my copy with me, but look for it because I think it explains what you are asking for.

+19  A: 

There are two kinds of reflection swimming around.

  1. Inspection by iterating over members of a type, enumerating its methods and so on.

    This is not possible with C++.
  2. Inspection by checking whether a class-type (class, struct, union) has a method or nested type, is derived from another particular type.

    This kind of thing is possible with C++ using template-tricks. Use boost::type_traits for many things (like checking whether a type is integral). For checking for the existance of a member function, use http://stackoverflow.com/questions/257288/possible-for-c-template-to-check-for-a-functions-existence#264088 . For checking whether a certain nested type exists, use plain SFINAE .

If you are rather looking for ways to accomplish 1), like looking how many methods a class has, or like getting the string representation of a class id, then i'm afraid there is no Standard C++ way of doing this. You have to use either

  • A Meta Compiler like the Qt Meta Object Compiler which translates your code adding additional meta informations.
  • A Framework constisting of macros that allow you to add the required meta-informations. You would need to tell the framework all methods, the class-names, base-classes and everything it needs.

C++ is made with speed in mind. If you want high-level inspection, like C# or Java has, then I'm afraid i have to tell you there is no way without some effort.

Johannes Schaub - litb
C++ is made with speed in mind, but the philosophy isn't "as fast as possible," instead it's, "you don't pay for it if you don't use it." I believe it's possible for a language to implement introspection in a way that fits with that philosophy, C++ just lacks it.
Joseph Garvin
@Joseph: How should that be done? It'd require all that metadata to be stored. Which means you have to pay for it, even if you don't use it. (Unless you could mark individual types as "supporting reflection", but then we're almost down where we might as well use the existing macro trickery.
jalf
MSalters
+3  A: 

I did something like what you're after once, and while it's possible to get some level of reflection and access to higher-level features, the maintenance headache might not be worth it. My system was used to keep the UI classes completely separated from the business logic through delegation akin to Objective-C's concept of message passing and forwarding. The way to do it is to create some base class that is capable of mapping symbols (I used a string pool but you could do it with enums if you prefer speed and compile-time error handling over total flexibility) to function pointers (actually not pure function pointers, but something similar to what Boost has with Boost.Function--which I didn't have access to at the time). You can do the same thing for your member variables as long as you have some common base class capable of representing any value. The entire system was an unabashed ripoff of Key-Value Coding and Delegation, with a few side effects that were perhaps worth the sheer amount of time necessary to get every class that used the system to match all of its methods and members up with legal calls: 1) Any class could call any method on any other class without having to include headers or write fake base classes so the interface could be predefined for the compiler; and 2) The getters and setters of the member variables were easy to make thread-safe because changing or accessing their values was always done through 2 methods in the base class of all objects.

It also led to the possibility of doing some really weird things that otherwise aren't easy in C++. For example I could create an Array object that contained arbitrary items of any type, including itself, and create new arrays dynamically by passing a message to all array items and collecting the return values (similar to map in Lisp). Another was the implementation of key-value observing, whereby I was able to set up the UI to respond immediately to changes in the members of backend classes instead of constantly polling the data or unnecessarily redrawing the display.

Maybe more interesting to you is the fact that you can also dump all methods and members defined for a class, and in string form no less.

Downsides to the system that might discourage you from bothering: adding all of the messages and key-values is extremely tedious; it's slower than without any reflection; you'll grow to hate seeing boost::static_pointer_cast and boost::dynamic_pointer_cast all over your codebase with a violent passion; the limitations of the strongly-typed system are still there, you're really just hiding them a bit so it isn't as obvious. Typos in your strings are also not a fun or easy to discover surprise.

As to how to implement something like this: just use shared and weak pointers to some common base (mine was very imaginatively called "Object") and derive for all the types you want to use. I'd recommend installing Boost.Function instead of doing it the way I did, which was with some custom crap and a ton of ugly macros to wrap the function pointer calls. Since everything is mapped, inspecting objects is just a matter of iterating through all of the keys. Since my classes were essentially as close to a direct ripoff of Cocoa as possible using only C++, if you want something like that then I'd suggest using the Cocoa documentation as a blueprint.

Michel
+3  A: 

The information does exist - but not in the format you need, and only if you export your classes. This works in Windows, I don't know about other platforms. Using the storage-class specifiers as in, for example:

class __declspec(export) MyClass
{
public:
    void Foo(float x);
}

This makes the compiler build the class definition data into the DLL/Exe. But it's not in a format that you can readily use for reflection.

At my company we built a library that interprets this metadata, and allows you to reflect a class without inserting extra macros etc. into the class itself. It allows functions to be called as follows:

MyClass *instance_ptr=new MyClass;
reflection::GetClass("MyClass")->GetFunction("Foo")->Invoke(instance_ptr,1.331);

This effectively does:

instance_ptr->Foo(1.331);

The Invoke(this_pointer,...) function has variable arguments. Obviously by calling a function in this way you're circumventing things like const-safety and so on, so these aspects are implemented as runtime checks.

I'm sure the syntax could be improved, and it only works on Win32 and Win64 so far. We've found it really useful for having automatic GUI interfaces to classes, creating properties in C++, streaming to and from XML and so on, and there's no need to derive from a specific base class. If there's enough demand maybe we could knock it into shape for release.

Roderick
+1  A: 

lack of built in reflection in C++ is the single reason why modern C++ is not used for web development (and lacks ORM and other frameworks)

You can try http://www.extreme.indiana.edu/reflcpp/

vlad
A: 

When I wanted reflection in C++ I read this article and improved upon what I saw there. Sorry, no can has. I don't own the result...but you can certainly get what I had and go from there.

I am currently researching, when I feel like it, methods to use inherit_linearly to make the definition of reflectable types much easier. I've gotten fairly far in it actually but I still have a ways to go. The changes in C++0x are very likely to be a lot of help in this area.

Noah Roberts
A: 

CAMP is a LGPL library that adds reflection to the C++ language using Boost. It doesn't require a specific preprocessing step in the compilation, but the binding has to be made manually.

philippe