Boost logo

Boost :

Subject: Re: [boost] [Boost-interest] C++ library for runtime-concepts (type-erasure)
From: Germán Diago (germandiago_at_[hidden])
Date: 2011-02-14 13:36:26


> 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.

I looked at Boost.Mirror some time ago, but I think that, for my own goals,
that is a too heavyweight dependency.

> A simple version of run-time reflection, useful for serialization:
>    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 think that Boost.serialization library is a good library, but if it
were written nowadays,
it would be done in another way. I think that the correct way when
c++0x is implemented
 with some trait that identifies the members that you want to serialize, and,
after that, return an in-memory object, like a string. Having the
information provided
by those members, you could implement generic
and custom serializations: binary, json, and whatever, without having
to code a special-purpose
format for your specific library. This way we can make libraries useful
to more people.

>
>>
>> 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:

Yes, I think it could be possible. Generating the runtime information from the
compile-time information is the right approach to not duplicate things. The only
downside is that you still have to make some kind of registration for
every type,
but that could be as simple as a single macro.

> 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.

With constexpr + user-defined literals, I think this can be done:

template <char...C>
struct Var_Name {
     //expand here C...
};

And with user-defined literals:

constexpr template <char... C> Var_Name<C...> operator _var();

now:

//We didn't loose the name!!!! Good c++0x...
typedef tuple<Var_Name<"name"_var>...

This should be valid c++0x.

>
> 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.

I think that's not possible in c++, but I'll try to investigate once I
have some time.

> 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?

I haven't tried those tests, but maybe it would take too long. It's
just the idea
I was implementing and that I had in my mind, but I don't know wether its
compile-times are practical.

> 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.

So, to summarize, we need:

-Static Type information -> Useful for serialization (I think that
boost.Serialization library is aging in this regard, although very
useful still today). I would try with a tuple trait approach.

-Type erasure. -> I'm trying to implement this one, and I think a nice
library can be built in c++/c++0x.
-RPC. -> This could be based in information registered for functions
through metaprogramming and pointer to member registration.
- Enable 'building' types with arbitrary member variables. -> This one
is pretty difficult.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk