Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

C++ Reflection

51 views
Skip to first unread message

Shannon Barber

unread,
Sep 19, 2002, 9:17:13 AM9/19/02
to
This is just a preliminary proof-of-concept, but I'm interested in
feedback from the community about adding reflection to C++.
This code has serious issues with access privileges (notice everything
is public) and requires manual definitions of the reflection
information. I'll continue work on this, but I think those issues
need to be resolved by some type of new language support.
My suggestion is not to add reflection to the language directly, but
to add new constructs that will allow one to add reflection to the
code in a controlled manor.

The idea is a special Reflection template generates typelist about the
properties & methods of the given template parameter. This makes
adding reflection unobtrusive to the reflected class. The most
pressing issue is how to access properties (and invoke methods). I
accomplish this by specializing an Accessor template for the given
class and the (largely) arbitrary property index/id. These accessor
classes are implemented here using macros, and is what would need to
be automated. (The code presented is non-standard as it specializes a
nested class, but this implementation detail is unimportant as it
could be emulated any number of ways.)

The last points of interest are the new Loki typelist iterator
constructs (so new they aren't in the CVS repository quite yet).
These two templates form a binding between the compile-time world and
the run-time world. The first one, IterateTypes, works with an
insertion iterator to generate & store data about the types in the
typelist. The second, StreamTypes, streams data into a given stream
object. I am convinced StreamTypes would allow the complete
automation of (de)serialization IFF there were a mechanism to generate
typelist & accessors for the properties.
Special cases (e.g. raw pointers) would need some extra handling. By
default it should be assumed that they point to one item, but there
needs to be a mechanism to override this and bind the size to a
functor (which could be a reflected accessor) which can determine the
number of elements.

This is the output of the program. It will generate the corresponding
output for any class that has a well-defined Reflection<Class>
template.

[output]
class std::vector<int,class std::allocator<int> >, class
std::vector<double,class std::allocator<double> >

3: 42, 3012, 110
2: 3.14159, 2.71828

Press any key to continue . . .
[/output]


[source]
#include <cassert>
#include <vector>
#include <typeinfo>
#include <iostream>

#include <Loki\TypeList.h>
#include <Loki\DataGenerator.h>

#define ACCESSORS \
template<class Class, int Index> \
struct _Accessor;

#define ACCESSOR(CLASS, TYPE, PROP_NAME, INDEX) \
template<>\
struct _Accessor<CLASS, INDEX>\
{\
typedef TYPE type;\
static type& extract(CLASS* obj)\
{\
return obj->PROP_NAME;\
}\
};\
typedef _Accessor<CLASS, INDEX> _Accessor##INDEX;


template<typename T>
struct Reflection;

struct TestCase1
{
std::vector<int> integers;
std::vector<double> reals;
};

template<>
struct Reflection<TestCase1>
{
struct Public
{
ACCESSORS;
ACCESSOR(TestCase1, std::vector<int>, integers, 0);
ACCESSOR(TestCase1, std::vector<double>, reals, 1);
typedef Loki::TL::MakeTypeList<_Accessor0, _Accessor1>::Result
Properties;
};
};

//Return the name (char*) given a type
template<typename Property>
struct property_type_name
{
const char* operator()()
{
return typeid(Property::type).name();
}
};

//Extract & return the property from the class
template<typename Property>
struct extract_property
{
template<class Class>
Property::type& operator()(Class* obj)
{
return Property::extract(obj);
}
};

//I hope this is self-explanitory...
template<typename FI, typename Stream>
Stream& write_csv(FI begin, FI end, Stream& s)
{
std::copy(begin, end-1, std::ostream_iterator<typename
FI::value_type>(s, ", "));
s << *(end-1);
return s;
}

template<class OS, typename T>
OS& operator<<(OS& os, std::vector<T>& v)
{
os << (int)v.size() <<": ";
write_csv(v.begin(), v.end(), os);
os << std::endl;
return os;
}

int main(int argc, char* argv[])
{
//Create the unwitting object
TestCase1 testcase1;

//Magic happens here
typedef Reflection<TestCase1>::Public::Properties props;

std::vector<const char*> names;
//Iterate types in the 'props' Typelist and put their
// names in a vector
Loki::TL::IterateTypes<props, property_type_name> gen;
gen(std::back_inserter(names));

//Write that vector out cout
write_csv(names.begin(), names.end(), std::cout);
std::cout << std::endl;
std::cout << std::endl;

//Put some data into testcase1
testcase1.integers.push_back(42);
testcase1.integers.push_back(3012);
testcase1.integers.push_back(110);
testcase1.reals.push_back(3.14159265358979);
testcase1.reals.push_back(2.71828182818281828);

//Stream the types in the 'props' Typelist through
// extract_property and send the results to std::cout
Loki::TL::StreamTypes<props, extract_property> stream_gen;
stream_gen(std::cout, &testcase1);
std::cout << std::endl;
system("pause");
return 0;
}
[/source]

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]

Ole Reinartz

unread,
Sep 20, 2002, 7:49:46 AM9/20/02
to
> The idea is a special Reflection template generates typelist about the
> properties & methods of the given template parameter. This makes
> adding reflection unobtrusive to the reflected class. The most
> pressing issue is how to access properties (and invoke methods). I
> accomplish this by specializing an Accessor template for the given
> class and the (largely) arbitrary property index/id. These accessor
> classes are implemented here using macros, and is what would need to
> be automated. (The code presented is non-standard as it specializes a
> nested class, but this implementation detail is unimportant as it
> could be emulated any number of ways.)

Did you have a look at open- c++?
http://www.csg.is.titech.ac.jp/~chiba/openc++.html

The project started with some type of runtime reflection long time ago. Currently
it offers a C++ preprocesor that allows compiletime reflection, which in turn
allows to add many extensions to the language, including runtime reflection. It
could at least solve the problem of automating the generation of reflection- data.

Ole

apm

unread,
Sep 20, 2002, 7:54:55 AM9/20/02
to
shannon...@myrealbox.com (Shannon Barber) wrote in message news:<de001473.02091...@posting.google.com>...

> This is just a preliminary proof-of-concept, but I'm interested in
> feedback from the community about adding reflection to C++.

What do you think of this Reflection package for C++ (below) ?

http://www.garret.ru/~knizhnik/cppreflection/docs/reflect.html

Regards,

Andrew Marlow.

Shannon Barber

unread,
Sep 23, 2002, 5:42:43 AM9/23/02
to
Ole Reinartz <ole.re...@gmx.de> wrote

> Did you have a look at open- c++?
> http://www.csg.is.titech.ac.jp/~chiba/openc++.html
>
> The project started with some type of runtime reflection long time ago. Currently
> it offers a C++ preprocesor that allows compiletime reflection, which in turn
> allows to add many extensions to the language, including runtime reflection. It
> could at least solve the problem of automating the generation of reflection- data.

I have briefly looked at OpenC++ before - I think I will perfect the
technique, then look into using OpenC++ to generate the reflection
templates.

Shannon Barber

unread,
Sep 23, 2002, 5:43:04 AM9/23/02
to
ap...@student.open.ac.uk (apm) wrote

> What do you think of this Reflection package for C++ (below) ?
>
> http://www.garret.ru/~knizhnik/cppreflection/docs/reflect.html

The various limitations of each technique are imposing, and I am
primarily interested in developing compile-time reflection - which
would relieve the imposing limitations for those various techniques.

0 new messages