
2011/2/14 Daniel Larimer <dlarimer@gmail.com>:
I have posted Boost.IDL to github complete with documentation here: http://bytemaster.github.com/boost_idl/index.html
https://github.com/bytemaster/boost_idl
The library is header only. It is included as part of the Boost.Defrag "incubating" projects.
I haven't carefully read the documentation (sorry, have no time now), but I thought a lot about a new serialization library. My opinion is that this library couples two things together: interfaces and reflection.
I think that the correct approach to this is:
1.- Build a general runtime concepts library (without reflection) I would welcome such a solution; however, everything idea I have come up with in this regard requires either verbose/ugly macros or almost as much work as manually rolling your type erasure according to a well-defined
On 2/14/11 5:14 AM, "Germán Diago" <germandiago@gmail.com> wrote: pattern.
2.- Build a reflection mechanism that would be possible for every c++ type to use (non-intrusive).
If you do not mind C++0x dependency and verbose macros, Boost.Mirror does this very well. Older versions of Boost.Mirror do not require C++0x and the developers of Boost.Mirror are also creating a tool that will auto-generate the required macros. My feeling is that if your code requires that much reflection and you are willing to use a pre-processor then chances are your compile times and binary sizes will become huge. If you are using a pre-processor then you might as well generate code directly rather than using templates and should probably be using a different language. A simple version of run-time reflection, useful for serialization: This is the easy part, create a macro that does this: DEFINE_VISITOR( InterfaceType, (member, 1)(sequence,3,optional) ) template<typename VisitorType, typename ExtraProperties> void visit( Visitor& v, InterfaceType& i, const char* name, ExtraProperties prop ) { v.accept( i.member, "member", 0 ); v.accept( i.sequence, "sequence", 0 ) } The above works well for serialization, but loses the member pointer for reflection. So perhaps the following alternative would work: v.accept( i, &InterfaceType::member, "member", 0 ); I would hope that any reasonable compiler would cause the performance of both variations to be identical considering all of the information required is present. However, I suspect that the first version would probably involve one less 'indirection' and thus perform better for serialization operations, while the second would be better for reflection. Any type can use the BOOST_IDL_INTERFACE() macro to define its reflection without using it for type erasure.
3.- Build serialization and other reflection mechanisms in top of these two different libraries.
It is funny you mention this, I am actively working on adding serialization features to Boost.IDL with the goal of providing more control over the 'Archive' format than Boost.Serialization. Specifically, I want to support JSON / Protocol Buffer serialization approach to support forward/backward compatibility.
I tried (but it's incomplete) a new reflection approach, and I think that with c++0x will be possible. The goal for this reflection library was serialization, so it wasn't a general reflection framework, but it was good enough to serialize objects.
My approach was to use a tuple that described every c++ member that a class had. It looked something like this:
class MyClass { typedef MyClass this_class;
std::string val_; float f_; public: typedef std::tuple<MEM_VARS2(val_, f_)> serializable_members_t; };
I suspect that your tuple approach could be combined with my visitor approach to offer two methods of reflection, runtime and compile time: DEFINE_MEMBERS( TYPE, (val_)(f_)...() ) typedef boost::fusion::vector< &TYPE::val_, &TYPE::f_, ... > TYPE ## MEMBERS The trouble is that even though we have compile time access to all of the member pointers, we have lost the 'name'. With some fancy magic to generate a const char* with external linkage one might be able to get the name into the template parameter as non-type template parameter. Even if you achieved complete static reflection with the above method, it would still not enable you to 'build' types with arbitrary member variables and methods. Perhaps using boost::fusion fused parameters you could simplify the number of permutations enough that it may be possible to generate a 'class' that given a method signature template parameter implements 'name' in terms of that signature. Correct me if I am wrong, but doesn't boost::fusion::vector<> explode compile times as the number of elements grows? Is tuple better? Would attempting to reflect an type with 50 fields in this manner be totally unfeasible?
And the rest was done by a general serialize member function (actually a family with boost::enable_if). With c++0x I could pass the variable names in tuples if we had user-defined literals and constexpr (at least, I think so). With this info, it's very easy to serialize objects in c++ (although I didn't study every single problem like inheritance and so on).
template <class T> std::string serialize(const T & t);
With reflection for members and runtime concepts, a framework for RPC can be built on top of those general and useful by themselves library.
I hope my opinion helped you.
Your ideas are good in theory and they are my ideal as well, but I have yet to reduce it to practice. Any ideas on that would be useful.
______________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost