D RTTI?

Artur Skawina art.08.09 at gmail.com
Wed Mar 7 15:04:58 PST 2012


On 03/07/12 00:19, H. S. Teoh wrote:
> On Tue, Mar 06, 2012 at 11:40:19PM +0100, Artur Skawina wrote:
>> On 03/06/12 20:37, H. S. Teoh wrote:
>>> On Tue, Mar 06, 2012 at 01:51:51AM +0100, Artur Skawina wrote:
>>> [...]
>>>> class A {
>>>>    string prop1;
>>>>    int prop2;
>>>>
>>>>    void serialize(this THIS)() {
>>>>       __serialize(cast(THIS*)&this);
>>>>    }
>>>> }
>>>>
>>>> void __serialize(T)(T* obj) {
>>>>    writef("%s {\n", typeid(*obj));
>>>>    foreach (name; __traits(allMembers, T)) {
>>>>       static if (__traits(compiles,&__traits(getMember,obj,name))) {
>>>>          alias typeof(__traits(getMember,obj,name)) MT;
>>>>          static if (is(MT==function))
>>>>             continue;
>>>>          else {
>>>>             auto m = __traits(getMember,obj,name);
>>>>             if (is(MT:const(char[])))
>>>>                writef("   %s %s = \"%s\";\n", typeid(MT), name, m);
>>>>             else
>>>>                writef("   %s %s = %s;\n", typeid(MT), name, m);
>>>>          }
>>>>       }
>>>>    }
>>>>    writef("}\n");
>>>> }
>>>>
>>>> And it will do the right thing for derived classes too.
>>> [...]
>>>
>>> Hmm, it only does the right thing for derived class if invoked with the
>>> derived class pointer. It doesn't work (and in retrospect can't possibly
>>> work, since "this THIS" is a compile-time parameter) if you only have
>>> the base class pointer.
[...]
>>> What I needed was for serialize() to be polymorphic at runtime, so it
>>> does have to be overloaded in every derived class. Hmph...  looks like I
>>> can't avoid using mixins. :-(
>>
>> If you can "register" the classes to be serialized then typeid() can
>> help the __serialize() implementation...
> 
> True. But TypeInfo doesn't let you access actual data members without
> using void* casts and pointer arithmetic, whereas compile-time
> introspection does.

What i meant is something like this:

    int prop2;
 
    void serialize(this THIS)() {
+      if (auto p = typeid(this) in serializers)
+         (*p)(&this);
+      else
       __serialize(cast(THIS*)&this);
    }
 }
@@ -14,6 +17,13 @@
    int propB2;
 }
 
+alias void delegate(void*) SDG;
+SDG[typeof(typeid(int))] serializers;
+
+void __register(T)(T* o) {
+   serializers[typeid(T)] = cast(SDG)(T* o) { __serialize(o); };
+}
+
 void __serialize(T)(T* obj) {
    writef("%s {\n", typeid(*obj));
    foreach (name; __traits(allMembers, T)) {


which doesn't need mixins in every derived class, you just need to
call __register with an instance once, before doing the serializing.
[it's a quick hack, written while typing this email; in real code
you probably want to stick to just one approach and assert when trying
to serialize an unknown type etc]

artur


More information about the Digitalmars-d-learn mailing list