
Is runtime reflection going to be available in boost soon? The last I have found on the subject is http://lists.boost.org/Archives/boost/2007/08/126006.php but I see nothing in the sandbox nor the vault. I have toyed with an implementation myself. It supports member variables and functions, multiple and virtual inheritance and object creation. Here is what it looks like. First a small hierarchy: class animal { /* ... */ }; class mammal : public virtual animal { /* ... */ }; class carnivore : public virtual animal{ /* ... */ }; class dog : public mammal, public carnivore{ /* ... */ }; Reflection info is filled like this: reflection_class<animal>::name("animal"); reflection_class<animal>::variable("age", &animal::age); // etc reflection_class<mammal>::name("mammal"); reflection_class<mammal>::base<animal>(virtual_); // etc reflection_class<carnivore>::name("carnivore"); reflection_class<carnivore>::base<animal>(virtual_); // etc reflection_class<dog>::name("dog"); reflection_class<dog>::base<mammal>(); reflection_class<dog>::base<carnivore>(); // a function reflection_class<dog>::function("bark", &dog::bark); // overloaded functions reflection_class<dog>::function<string (dog::*)(void) const>("name", &dog::name); reflection_class<dog>::function<void (dog::*)(const string&)>("name", &dog::name); // constructor reflection_class<dog>::constructor<void* (*)()>(); // etc And here how it's used: animal* pa(new dog); object o(downcast(pa)); // recover dynamic type // access member variable inherited from virtual base `animal' member_variable<int> dog_age(o, "age"); int age = o[dog_age]; // call member function member_function<string (object::*)() const> dog_name(o, "name"); string name = o[dog_name](); // create a dog using default ctor object o("dog"); Ok, there is a bit more to it (e.g. support macros, ambiguity detection, handling of shadowed members, overloaded ctors) but the important part is shown above. All in all it is a foundation upon which one can build multimethods, generic object processing (like Perl's data::Dumper), serialization, object-relational mapping and all sorts of nice tools. Does anybody see interest in this work? Jean-Louis

On Sat, Nov 1, 2008 at 2:46 PM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
Jean-Louis Leroy wrote:
Is runtime reflection going to be available in boost soon?
Why runtime? A trait-based system like you describe would be best used with compile-time reflection...
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
I don't know if it's what you need, but you can look at the Mirror reflection/introspection library in the vault or in the sandbox. It is not difficult to make a polymorphic wrapper around the compile-time meta-objects provided by this library. I'm planning to implement this myself when I have the basic stuff done, but currently i'm busy with some other things, so unfortunately it is going to take some time. best regards, -- ________________ ::matus_chochlik

Hello Matus.
I don't know if it's what you need, but you can look at the Mirror reflection/introspection library in the vault or in the sandbox.
I'm taking a look at it. It looks like my work picks up where yours stops. It is certainly worth making my library capable of perusing mirror's compile-time info. Or maybe my work should be merged in mirror... I'll try to upload my stuff to the sandbox before leaving for vacation this thursday.
It is not difficult to make a polymorphic wrapper around the compile-time meta-objects provided by this library.
It's not very difficult but it's not very easy either, because you have to deal with address adjustment in presence of multiple inheritance. J-L

I'm working on Boost.Reflection - see http://boost-extension.blogspot.com. I gave a presentation on it at BoostCon this year. Jeremy Pack On Fri, Oct 31, 2008 at 9:20 PM, Jean-Louis Leroy <jl@yorel.be> wrote:
Is runtime reflection going to be available in boost soon? The last I have found on the subject is http://lists.boost.org/Archives/boost/2007/08/126006.php but I see nothing in the sandbox nor the vault.
I have toyed with an implementation myself. It supports member variables and functions, multiple and virtual inheritance and object creation.
Here is what it looks like.
First a small hierarchy:
class animal { /* ... */ }; class mammal : public virtual animal { /* ... */ }; class carnivore : public virtual animal{ /* ... */ }; class dog : public mammal, public carnivore{ /* ... */ };
Reflection info is filled like this:
reflection_class<animal>::name("animal"); reflection_class<animal>::variable("age", &animal::age); // etc
reflection_class<mammal>::name("mammal"); reflection_class<mammal>::base<animal>(virtual_); // etc
reflection_class<carnivore>::name("carnivore"); reflection_class<carnivore>::base<animal>(virtual_); // etc
reflection_class<dog>::name("dog"); reflection_class<dog>::base<mammal>(); reflection_class<dog>::base<carnivore>(); // a function reflection_class<dog>::function("bark", &dog::bark); // overloaded functions reflection_class<dog>::function<string (dog::*)(void) const>("name", &dog::name); reflection_class<dog>::function<void (dog::*)(const string&)>("name", &dog::name); // constructor reflection_class<dog>::constructor<void* (*)()>(); // etc
And here how it's used:
animal* pa(new dog);
object o(downcast(pa)); // recover dynamic type
// access member variable inherited from virtual base `animal' member_variable<int> dog_age(o, "age"); int age = o[dog_age];
// call member function member_function<string (object::*)() const> dog_name(o, "name"); string name = o[dog_name]();
// create a dog using default ctor object o("dog");
Ok, there is a bit more to it (e.g. support macros, ambiguity detection, handling of shadowed members, overloaded ctors) but the important part is shown above. All in all it is a foundation upon which one can build multimethods, generic object processing (like Perl's data::Dumper), serialization, object-relational mapping and all sorts of nice tools.
Does anybody see interest in this work?
Jean-Louis _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Jeremy Pack wrote:
I'm working on Boost.Reflection - see http://boost-extension.blogspot.com. I gave a presentation on it at BoostCon this year.
Thanks. I have looked at the code in the svn repo (which I had not found when browsing the boost website). Do you have an example of how it's used? Is it similar to my example? Can it cope with multiple or virtual inheritance? In your code I don't see where address adjustment is done... Jean-Louis

Jean-Louis, Boost.Reflection handles multiple and virtual inheritance fine. The main difference between the approaches is that Boost.Reflection does not require any global structures. A basic example similar to yours would look something like: map<string, reflection> reflections; reflections["animal"].reflect<animal>() // doSomething's parameters are deduced automatically if possible. .function(&animal::doSomething, "doSomething") .data(&someData, "someData"); // etc. reflections["baboon"].reflect<baboon>() .constructor() // use the default constructor .constructor<int, const char*>() // provide a parameterized constructor .inherits<animal>("animal") .function(&baboon::someAnimalThing, "someAnimalThing"); reflection& baboon_reflection = reflections["baboon"]; instance_constructor baboon_factory = baboon_reflection.get_constructor(); instance baboon_instance = baboon_factory.create(); reflected_function<> someAnimalThing = baboon_reflection.get_function("someAnimalThing"); // Call someAnimalThing someAnimalThing(baboon_instance); reflected_function<int, const string&> doSomething = baboon_reflection.get_function("doSomething"); doSomething(baboon_instance, 5, "hello"); // etc. I wrote that from memory so some of the syntax may be off (I don't have enough time today to do more with it). The library interface is changing a bit over the next few weeks as I prepare to submit the Boost.Extension library (of which this is a part) for review. The code will be moving from the libs/reflection directory to the libs/extension directory, switching namespaces, etc. Jeremy On Sat, Nov 1, 2008 at 9:05 PM, Jean-Louis Leroy <jl@yorel.be> wrote:
Jeremy Pack wrote:
I'm working on Boost.Reflection - see http://boost-extension.blogspot.com. I gave a presentation on it at BoostCon this year.
Thanks. I have looked at the code in the svn repo (which I had not found when browsing the boost website).
Do you have an example of how it's used? Is it similar to my example? Can it cope with multiple or virtual inheritance? In your code I don't see where address adjustment is done...
Jean-Louis
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Jeremy Pack wrote:
Jean-Louis, Boost.Reflection handles multiple and virtual inheritance fine.
Does the version from http://boost-extension.blogspot.com/2008/07/latest-release-downloadable.html contain support for inheritance already? My primary interest is not in reflection per se, for me it's just a tool upon which one can build generic object-processing tools like dumping objects to text descriptions or XML or implementing object-relational mapping. Once we have reflection, we need a way to deal with fields in a generic manner, whatever their type: int, vector<int>, vector< vector<int> > etc. One solution is to reflect the structure of the field's type as well: make the field class contain a pointer to a polymorphic type object, from which one derives int_type, a vector_type - which contains in turn a pointer to the element's type - etc. Pattern freaks will call it a composite ;-) The next step is multimethods. Once we have them we can write code like this: // using BS's proposed syntax in D&E void process_type(virtual type&, virtual processor&, void*); void process(instance i, processor& p) for each field (i) process_type(*field->type, p, field->address(i)) class text_dumper : public processor { ... }; void process_type(virtual int_type& t, virtual text_processor& p, char* pv) { p << *reinterpret_cast<int*>(pv); } void process_type(virtual vector_type& t, virtual text_processor& p, char* pv) { p.indent(); char *iter = t.begin(pv), last = t.end(pv); while (iter != last) { process_type(t.element_type, p, iter); t.forward(iter); } p.outdent(); } What do you think of the idea? Jean-Louis

Jean-Louis, What you want to do would require storing a great deal of extra information, in addition to that stored by Boost.Reflection. Since one of my primary emphases is performance, I doubt that my library is an ideal framework upon which to build what you propose. I would imagine though that much of the code could be very useful to you. Have you looked at GCCXML? It could very well give you much of the functionality that you desire (class names, function names and signatures, types with data etc.) I'm not sure if the version of Boost.Reflection in the Sandbox contains the inheritance code. If not, I'll just need to make sure I have unit tests together for it and then I'll submit it. Given the normal speed of C++ evolution, I expect to wait quite a while before being able to write multi-methods. Jeremy On Mon, Nov 3, 2008 at 3:17 PM, Jean-Louis Leroy <jl@yorel.be> wrote:
Jeremy Pack wrote:
Jean-Louis, Boost.Reflection handles multiple and virtual inheritance fine.
Does the version from http://boost-extension.blogspot.com/2008/07/latest-release-downloadable.html... support for inheritance already?
My primary interest is not in reflection per se, for me it's just a tool upon which one can build generic object-processing tools like dumping objects to text descriptions or XML or implementing object-relational mapping.
Once we have reflection, we need a way to deal with fields in a generic manner, whatever their type: int, vector<int>, vector< vector<int> > etc. One solution is to reflect the structure of the field's type as well: make the field class contain a pointer to a polymorphic type object, from which one derives int_type, a vector_type - which contains in turn a pointer to the element's type - etc. Pattern freaks will call it a composite ;-)
The next step is multimethods. Once we have them we can write code like this:
// using BS's proposed syntax in D&E void process_type(virtual type&, virtual processor&, void*);
void process(instance i, processor& p) for each field (i) process_type(*field->type, p, field->address(i))
class text_dumper : public processor { ... };
void process_type(virtual int_type& t, virtual text_processor& p, char* pv) { p << *reinterpret_cast<int*>(pv); }
void process_type(virtual vector_type& t, virtual text_processor& p, char* pv) { p.indent(); char *iter = t.begin(pv), last = t.end(pv); while (iter != last) { process_type(t.element_type, p, iter); t.forward(iter); } p.outdent(); }
What do you think of the idea?
Jean-Louis
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Jeremy,
What you want to do would require storing a great deal of extra information, in addition to that stored by Boost.Reflection. Since one of my primary emphases is performance, I doubt that my library is an ideal framework upon which to build what you propose. I would imagine though that much of the code could be very useful to you.
Is it so? It's just one extra pointer per field. Hmm. For what I have in mind I also need to ask to a class what its subclasses are...
Have you looked at GCCXML? It could very well give you much of the functionality that you desire (class names, function names and signatures, types with data etc.)
It looks nice but it's gcc-specific. Currently I use MS Visual Express 2008.
I'm not sure if the version of Boost.Reflection in the Sandbox contains the inheritance code. If not, I'll just need to make sure I have unit tests together for it and then I'll submit it.
I'm really curious :-)
Given the normal speed of C++ evolution, I expect to wait quite a while before being able to write multi-methods.
Oh but we don't wait: we emulate them. They won't be very fast but for my needs it's not very important, as I plan to use them to build graphs of objects that mirrors the graph of reflection objects - then put the real functionality in the new graph as regular methods. Now there's a problem. I have been asked via private email to show my code. I have commit access to the sandbox. I see that there is no reflection directory at the top level yet, instead you use boost/reflection and libs/reflection. However I assume that you want to reorganize your library to follow the suggested layout? And thus use boost/reflection? What's the normal way of solving this problem? We have a bit of luck though: you use namespace boost::reflections - and I use boost::reflection sans s. Jean-Louis

Now there's a problem. I have been asked via private email to show my code. I have commit access to the sandbox. I see that there is no reflection directory at the top level yet, instead you use boost/reflection and libs/reflection. However I assume that you want to reorganize your library to follow the suggested layout? And thus use boost/reflection? What's the normal way of solving this problem?
Okay, I called mine 'introspection'. It's less Java-esque and since I use darcs here I'll be able to un-rename it later if need be :-) Jean-Louis

Jean-Louis, > > What you want to do would require storing a great deal of extra > > information, in addition to that stored by Boost.Reflection. Since one > > of my primary emphases is performance, I doubt that my library is an > > ideal framework upon which to build what you propose. I would imagine > > though that much of the code could be very useful to you. > > Is it so? It's just one extra pointer per field. > > Hmm. For what I have in mind I also need to ask to a class what its subclasses are... > > > Have you looked at GCCXML? It could very well give you much of the > > functionality that you desire (class names, function names and > > signatures, types with data etc.) > > It looks nice but it's gcc-specific. Currently I use MS Visual Express 2008. Have a look at the CERN's Reflex library (part of the ROOT library): http://root.cern.ch/ We use it extensively here, I think it's more powerful than what you ask for. It's based on GCCXML for parsing, uses Python scripts to generate C++ code that's compiled into your application/DLL. A bit like boost::python with pygccxml, but a bit less clean. It's got a few quirks, but it works pretty well. We're using it on Visual Studio-only projects, so GCCXML isn't a problem. JF

Hi Jean-Louis, I've merged several of Your posts so I can reply in one message, lazy me, sorry ;-P
I'm taking a look at it. It looks like my work picks up where yours stops. It is certainly worth making my library capable of perusing mirror's compile-time info. Or maybe my work should be merged in mirror...
I was thinking about writing a separate run-time library that would use Mirror as the source of the basic compile-time info. My idea is to define an abstract interface similar to the mirror's but polymorphic.
I'll try to upload my stuff to the sandbox before leaving for vacation this thursday.
I would be glad to work together with somebody on this, but I ain't going to make any promises ;), because right now I'm in a kind of deadline situation so don't have much free time to work on Mirror. Actually we've talked with Joel Falcou that we could work together, but ... since then I hardly found some time to work on the mirror docs. Hope it will be better at the end of this / the beginning of the next year. On Tue, Nov 4, 2008 at 12:17 AM, Jean-Louis Leroy <jl@yorel.be> wrote:
Jeremy Pack wrote:
Jean-Louis, Boost.Reflection handles multiple and virtual inheritance fine.
Does the version from http://boost-extension.blogspot.com/2008/07/latest-release-downloadable.html contain support for inheritance already?
My primary interest is not in reflection per se, for me it's just a tool upon which one can build generic object-processing tools like dumping objects to text descriptions or XML or implementing object-relational mapping.
Support for serialization and object-relational mapping is also one of my motivations for writing a compile time reflection library. Actually it is sad that the C++'s "reflection" abilities are limited to ::std::type_info, the typeof operator and bunch of other stuff, because compilers have a lot of useful information that the programmers could use, but cannot access in any portable and standardized way. The potential authors of a proposal of a good compile-time reflection facility for C++ will be my heroes. :) Sure, there are tools like gcc2xml, openC++ and some others but most of them are platform/compiler specific and using them in big projects tends to be difficult. But I was thinking (suprisingly enough) about gcc2xml being used as an optional support for automated registering of things into mirror, on those platforms where it is available.
Once we have reflection, we need a way to deal with fields in a generic manner, whatever their type: int, vector<int>, vector< vector<int> > etc. One solution is to reflect the structure of the field's type as well: make the field class contain a pointer to a polymorphic type object, from which one derives int_type, a vector_type - which contains in turn a pointer to the element's type - etc. Pattern freaks will call it a composite ;-)
The next step is multimethods. Once we have them we can write code like this:
// using BS's proposed syntax in D&E void process_type(virtual type&, virtual processor&, void*);
void process(instance i, processor& p) for each field (i) process_type(*field->type, p, field->address(i))
class text_dumper : public processor { ... };
void process_type(virtual int_type& t, virtual text_processor& p, char* pv) { p << *reinterpret_cast<int*>(pv); }
void process_type(virtual vector_type& t, virtual text_processor& p, char* pv) { p.indent(); char *iter = t.begin(pv), last = t.end(pv); while (iter != last) { process_type(t.element_type, p, iter); t.forward(iter); } p.outdent(); }
What do you think of the idea?
Mirror provides class and class instance *traversals*, which "guide" custom user-defined generic visitors through the structure of a class and optionally also allow to work with instances of that class in a generic way. Generaly the traversal calls the visitor's member functions like enter_type, leave_type, enter_base_classes, leave_base_classes, enter_attributes, leave_attributes, etc. depending on the reflected class' declaration, with appropriate arguments. The traversals can also provide the visitors with x-path-like ;) meta-paths that can give insight about the context in which the visited base_class, attribute, ... etc is visited. Another way how to work with member attributes, base classes, etc. is to use the algorithms like for_each or the iterators provided by mirror. This features are unfortunately still undocumented, there are however several examples showing how to use them included in Mirror.
Jean-Louis
Best ________________ ::matus_chochlik

Matus Chochlik a écrit :
Actually we've talked with Joel Falcou that we could work together, but ... since then I hardly found some time to work on the mirror docs. Hope it will be better at the end of this / the beginning of the next year.
I'm also guilty as charged to not pursuing further. Note also that my identity library has a far smaller scope than whole Mirror. Anyway, if needed I can lend a hand to whoever need it.

I've merged several of Your posts so I can reply in one message, lazy me, sorry ;-P
Excellent idea :-) I have renamed my library 'introspection' (to avoid clashing with Jeremy's work) and committed it to the sandbox. Today I wet my feet with Boost.Mirror. Using the doc (and the source code ;-)) I was able to make the code at the bottom of this message work. After a couple of hours 1/ I was very impressed 2/ I had a headache 3/ I was convinced that building runtime reflection on top of your work will be easy and 4/ I had found a bug ;-)
But I was thinking (suprisingly enough) about gcc2xml being used as an optional support for automated registering of things into mirror, on those platforms where it is available.
Sure, we must write the backend in such a way that it is useable stand-alone then write generators. My experience is that generators are fine as long as you have only one of them in a project but two won't coexist well, usually. I'm running out of time, I have to work on serious things, namely preparing my trip to ... Slovakia ! Here's my Mirror hello-world, with the bug report: #include <iostream> #include <boost/mirror/meta_class.hpp> #include <boost/mirror/meta_inheritance.hpp> #include <boost/mirror/algorithm/for_each.hpp> using namespace std; using namespace boost; using namespace boost::mirror; struct animal { int age; }; struct mammal : virtual animal { }; struct carnivore : virtual animal { }; struct dog : mammal, carnivore { }; namespace boost { namespace mirror { BOOST_MIRROR_REG_TYPE_GLOBAL_SCOPE(animal) BOOST_MIRROR_REG_CLASS_ATTRIBS_BEGIN(animal) BOOST_MIRROR_REG_SIMPLE_CLASS_ATTRIB(_, int, age) BOOST_MIRROR_REG_CLASS_ATTRIBS_END BOOST_MIRROR_REG_TYPE_GLOBAL_SCOPE(mammal) BOOST_MIRROR_REG_BASE_CLASSES_BEGIN(mammal) BOOST_MIRROR_REG_VIRTUAL_BASE_CLASS(0, public, animal) BOOST_MIRROR_REG_BASE_CLASSES_END // watch out: BOOST_MIRROR_REG_SINGLE_BASE_CLASS_VIRTUAL(mammal, public, animal) // doesn't work because it calls BOOST_MIRROR_REG_BASE_CLASS_VIRTUAL // instead of BOOST_MIRROR_REG_VIRTUAL_BASE_CLASS BOOST_MIRROR_REG_TYPE_GLOBAL_SCOPE(carnivore) BOOST_MIRROR_REG_BASE_CLASSES_BEGIN(carnivore) BOOST_MIRROR_REG_VIRTUAL_BASE_CLASS(0, public, animal) BOOST_MIRROR_REG_BASE_CLASSES_END BOOST_MIRROR_REG_TYPE_GLOBAL_SCOPE(dog) BOOST_MIRROR_REG_BASE_CLASSES_BEGIN(dog) BOOST_MIRROR_REG_BASE_CLASS(0, public, mammal) BOOST_MIRROR_REG_BASE_CLASS(1, public, carnivore) BOOST_MIRROR_REG_BASE_CLASSES_END } } struct print_attribute { template<typename ATTRIBUTE> void operator()(ATTRIBUTE) { cout << ATTRIBUTE::get_name(mpl::false_(), std::char_traits<char>()) << endl; } }; struct print_base { template<typename CLASS> void display(CLASS, virtual_base_) { cout << "virtual " << CLASS::meta_base_class::get_name(mpl::false_(), std::char_traits<char>()) << endl; } template<typename CLASS> void display(CLASS, nonvirtual_base_) { cout << CLASS::meta_base_class::get_name(mpl::false_(), std::char_traits<char>()) << endl; } template<typename CLASS> void operator()(CLASS c) { display(c, CLASS::inheritance_specifier()); } }; int main() { mirror::for_each< meta_class<animal>::attributes >(print_attribute()); mirror::for_each< meta_class<mammal>::base_classes >(print_base()); mirror::for_each< meta_class<dog>::base_classes >(print_base()); return 0; } Cordially, Jean-Louis

On Tue, Nov 4, 2008 at 9:47 PM, Jean-Louis Leroy <jl@yorel.be> wrote:
I have renamed my library 'introspection' (to avoid clashing with Jeremy's work) and committed it to the sandbox.
FYI there already is a library named introspection in the vault written by Joel Falcou.
Today I wet my feet with Boost.Mirror. Using the doc (and the source code ;-)) I was able to make the code at the bottom of this message work. After a couple of hours 1/ I was very impressed 2/ I had a headache 3/ I was convinced that building runtime reflection on top of your work will be easy and 4/ I had found a bug ;-)
1/ I hope the impression was positive ;), thanks 2/ Sorry about the headache ;) 3/ I hope I will be helpful 4/ Thanks for spotting it !
Sure, we must write the backend in such a way that it is useable stand-alone then write generators. My experience is that generators are fine as long as you have only one of them in a project but two won't coexist well, usually.
sounds reasonable.
I'm running out of time, I have to work on serious things, namely preparing my trip to ... Slovakia !
Well, hope we can manage meet.
Here's my Mirror hello-world, with the bug report:
Whee, this is the first program using mirror written by somebody else than myself, that I've seen so far :)
#include <iostream>
#include <boost/mirror/meta_class.hpp> #include <boost/mirror/meta_inheritance.hpp> #include <boost/mirror/algorithm/for_each.hpp>
using namespace std; using namespace boost; using namespace boost::mirror;
struct animal { int age; };
struct mammal : virtual animal { };
struct carnivore : virtual animal { };
struct dog : mammal, carnivore { };
namespace boost { namespace mirror {
BOOST_MIRROR_REG_TYPE_GLOBAL_SCOPE(animal) BOOST_MIRROR_REG_CLASS_ATTRIBS_BEGIN(animal) BOOST_MIRROR_REG_SIMPLE_CLASS_ATTRIB(_, int, age) BOOST_MIRROR_REG_CLASS_ATTRIBS_END
BOOST_MIRROR_REG_TYPE_GLOBAL_SCOPE(mammal) BOOST_MIRROR_REG_BASE_CLASSES_BEGIN(mammal) BOOST_MIRROR_REG_VIRTUAL_BASE_CLASS(0, public, animal) BOOST_MIRROR_REG_BASE_CLASSES_END
// watch out: BOOST_MIRROR_REG_SINGLE_BASE_CLASS_VIRTUAL(mammal, public, animal) // doesn't work because it calls BOOST_MIRROR_REG_BASE_CLASS_VIRTUAL // instead of BOOST_MIRROR_REG_VIRTUAL_BASE_CLASS
Again, thanks for your bug report, I'm going to fix it ASAP.
BOOST_MIRROR_REG_TYPE_GLOBAL_SCOPE(carnivore) BOOST_MIRROR_REG_BASE_CLASSES_BEGIN(carnivore) BOOST_MIRROR_REG_VIRTUAL_BASE_CLASS(0, public, animal) BOOST_MIRROR_REG_BASE_CLASSES_END
BOOST_MIRROR_REG_TYPE_GLOBAL_SCOPE(dog) BOOST_MIRROR_REG_BASE_CLASSES_BEGIN(dog) BOOST_MIRROR_REG_BASE_CLASS(0, public, mammal) BOOST_MIRROR_REG_BASE_CLASS(1, public, carnivore) BOOST_MIRROR_REG_BASE_CLASSES_END
} }
struct print_attribute { template<typename ATTRIBUTE> void operator()(ATTRIBUTE) { cout << ATTRIBUTE::get_name(mpl::false_(), std::char_traits<char>()) << endl; } };
struct print_base { template<typename CLASS> void display(CLASS, virtual_base_) { cout << "virtual " << CLASS::meta_base_class::get_name(mpl::false_(), std::char_traits<char>()) << endl; } template<typename CLASS> void display(CLASS, nonvirtual_base_) { cout << CLASS::meta_base_class::get_name(mpl::false_(), std::char_traits<char>()) << endl; } template<typename CLASS> void operator()(CLASS c) { display(c, CLASS::inheritance_specifier()); } };
int main() { mirror::for_each< meta_class<animal>::attributes >(print_attribute()); mirror::for_each< meta_class<mammal>::base_classes >(print_base()); mirror::for_each< meta_class<dog>::base_classes >(print_base()); return 0; }
Cordially, Jean-Louis _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Best, --matus
participants (6)
-
Jean-Francois Bastien
-
Jean-Louis Leroy
-
Jeremy Pack
-
Joel Falcou
-
Mathias Gaunard
-
Matus Chochlik