Saturday, June 27, 2009

c++ reflection

C++ has reflection. However it's currently very limited. The reflection I'm talking about is the new type_traits libraries. They are in boost, where in the TR1, and will be in in c++0x. So C++ supports without language changes a limited reflection system, often called static reflection or compile time reflection.

To make C++'s reflection compete with the likes of Java or C# we need three things.

1) Reflection needs to be more complete. We need to way to access method, and member information from classes.

2) Access to these facilities at runtime.

3) Reflection on attributes

The first is easy to design, though possibly difficult for compiler makers. Looking at gccxml I hope it's not too hard

The second is easy as well. The trick is to remember the C++ mantra
Don't pay for what you don't use.

Provide a runtime library that wraps the static reflection. The user is required to instantiate the library. Reflection of methods and members would need to return pointers to object it's describing.

The third is hard to plan for at this point as attributes have only just been added to c++.

Here are the new metamethods needed by the type_traits library complete static reflection. The new metamethods are similar to function_traits which currently exists in the type_traits library.
  • class_traits
  • union_traits
  • class_member_traits
  • class_method_traits
  • internal_class_traits
  • base_class_traits


I've posted many of these ideas already in comp.lang.c++.moderated

enum class visibilty_t
{
e_public,
e_protected,
e_private,
e_invisible // for private members of base classes.
};

typedef< typename Type >
struct class_traits
{
typedef Type type;

constexpr char[] name;
constexpr char[] mangled_name;
constexpr unsigned num_members;
constexpr unsigned num_methods;
constexpr unsigned num_classes;
constexpr unsigned num_unions;
constexpr unsigned num_bases;
};

template< typename Type >
struct union_traits
{
typedef Type type;

constexpr char[] name;
constexpr char[] mangle_name;
constexpr unsigned num_types;
typedef some_type memberN_type;
};

template< typename Type, unsigned Number >
struct class_member_traits
{
typedef Type parent_type;
constexpr unsigned number = Number;

constexpr char[] name;
constexpr char[] mangled_name;
constexpr visibility_t visibility;
constexpr bool is_inherited;
constexpr bool is_const;
typedef some_type type;
typedef some_type pointer_type;

constexpr pointer_type pointer = &some_class_member;
};

template< typename Type, unsigned Number >
struct class_method_traits
{
typedef Type parent_type;
constexpr unsigned number = Number;

constexpr char[] name;
constexpr char[] mangled_name;
constexpr char[] signiture;
constexpr visibility_t visibility;
constexpr bool is_inherited;
constexpr bool is_const;
constexpr bool is_virtual;
constexpr bool is_pure;
typedef some_type type;
typedef some_type pointer_type;

constexpr pointer_type pointer = &some_class_method;
};

template< typename Type, unsigned Number >
struct internal_class_traits
{
typedef Type parent_type;
constexpr unsigned number = Number;

constexpr visibility_t visibility;
typedef some_type type;
};

template< typename Type, unsigned Number >
struct internal_union_traits
{
typedef Type parent_type;
constexpr unsigned number = Number;

constexpr visibility_t visibility;
typedef some_type type;
};

template< typename Type, unsigned Number >
struct base_class_traits
{
typedef Type super_type;
constexpr unsigned number = Number;

constexpr visibility_t visibility;
constexpr bool is_virtual;
typedef some_type type;
};


The following a bit more complicated. namespaces don't have types. But it would be nice to enumerate all members of a namespace. My solution is a traits class that takes a member of the namespace. Types most internal namespace would be enumerated. eg namespace_traits would enumerate the contents of outer::inner and namespace_traits would enumerate the contents of outer. namespace_traits only enumerates complete types and any functions currently visible.


template< typename In_namespace >
struct namespace_traits
{
typedef In_namespace in_namespace_type;

constexpr unsigned num_classes;
typedef some_type classN_type;

constexpr unsigned num_unions;
typedef some_type unionN_type;

constexpr unsigned num_functions;
};

template< typename In_namespace, unsigned Function_number >
struct namespace_function_traits
{
typedef In_namespace in_namespace_type;
constexpr unsigned number = Function_number;

constexpr char[] name;
constexpr char[] signature;
constexpr char[] mangled_name;

typedef some_function_type type;
typedef type* pointer_type;

constexpr pointer_type pointer = &function_name;
};

No comments: