www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - D RTTI?

reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
I know D doesn't really have RTTI yet, but I'm experimenting with
"faking" it by doing something like:

	class A {
		string prop1;
		int prop2;
		...
		void serialize() {
			__serialize(this);
		}
	}

	void __serialize(T)(T obj) {
		writeln(typeid(obj));
		foreach (name; __traits(derivedMembers, T)) {
			writefln("%s = %s", name,
				__traits(getMember,obj,name));
		}
	}

The only thing is, serialize() has to be declared in every derived
class, because T needs to be known at compile-time. Is there a way to
"automate" this? I.e., automatically insert the serialize() boilerplate
code into derived classes?

(P.S.  D just took on brand new levels of cool when I realized I could
do something like this. Imagine doing this with C++ templates...  ugh!
What a painful thought!)


T

-- 
Tech-savvy: euphemism for nerdy.
Mar 05 2012
next sibling parent reply Justin Whear <justin economicmodeling.com> writes:
On Mon, 05 Mar 2012 12:16:14 -0800, H. S. Teoh wrote:

 I know D doesn't really have RTTI yet, but I'm experimenting with
 "faking" it by doing something like:
 
 	class A {
 		string prop1;
 		int prop2;
 		...
 		void serialize() {
 			__serialize(this);
 		}
 	}
 
 	void __serialize(T)(T obj) {
 		writeln(typeid(obj));
 		foreach (name; __traits(derivedMembers, T)) {
 			writefln("%s = %s", name,
 				__traits(getMember,obj,name));
 		}
 	}
 
 The only thing is, serialize() has to be declared in every derived
 class, because T needs to be known at compile-time. Is there a way to
 "automate" this? I.e., automatically insert the serialize() boilerplate
 code into derived classes?
 
 (P.S.  D just took on brand new levels of cool when I realized I could
 do something like this. Imagine doing this with C++ templates...  ugh!
 What a painful thought!)
 
 
 T

The normal approach is to use a string mixin statement in each derived class: template Serializable() { enum Serializable = q{...your code here...}; } class B : A { mixin(Serializable); } Unfortunately, I don't believe there's any mechanism to order derived classes to automatically perform the mixin.
Mar 05 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 03/05/2012 11:33 PM, H. S. Teoh wrote:
 On Mon, Mar 05, 2012 at 08:41:53PM +0000, Justin Whear wrote:
 On Mon, 05 Mar 2012 12:16:14 -0800, H. S. Teoh wrote:

 I know D doesn't really have RTTI yet, but I'm experimenting with
 "faking" it by doing something like:

 	class A {
 		string prop1;
 		int prop2;
 		...
 		void serialize() {
 			__serialize(this);
 		}
 	}

 	void __serialize(T)(T obj) {
 		writeln(typeid(obj));
 		foreach (name; __traits(derivedMembers, T)) {
 			writefln("%s = %s", name,
 				__traits(getMember,obj,name));
 		}
 	}

 The only thing is, serialize() has to be declared in every derived
 class, because T needs to be known at compile-time. Is there a way to
 "automate" this? I.e., automatically insert the serialize() boilerplate
 code into derived classes?

 (P.S.  D just took on brand new levels of cool when I realized I could
 do something like this. Imagine doing this with C++ templates...  ugh!
 What a painful thought!)


 T

The normal approach is to use a string mixin statement in each derived class: template Serializable() { enum Serializable = q{...your code here...}; } class B : A { mixin(Serializable); } Unfortunately, I don't believe there's any mechanism to order derived classes to automatically perform the mixin.

OK, it's a bit ugly I supopse, but I can live with that. Is there a way to tell whether or not a given class is a derived class or not? I'm using the Serializable template to insert serialize() into the class, and for derived classes I need to insert "override void serialize() ..." but for the base class I have to omit "override". How can I detect this in the template? Thanks! T

You can check typeof(this).
Mar 05 2012
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-03-05 21:16, H. S. Teoh wrote:
 I know D doesn't really have RTTI yet, but I'm experimenting with
 "faking" it by doing something like:

 	class A {
 		string prop1;
 		int prop2;
 		...
 		void serialize() {
 			__serialize(this);
 		}
 	}

 	void __serialize(T)(T obj) {
 		writeln(typeid(obj));
 		foreach (name; __traits(derivedMembers, T)) {
 			writefln("%s = %s", name,
 				__traits(getMember,obj,name));
 		}
 	}

 The only thing is, serialize() has to be declared in every derived
 class, because T needs to be known at compile-time. Is there a way to
 "automate" this? I.e., automatically insert the serialize() boilerplate
 code into derived classes?

 (P.S.  D just took on brand new levels of cool when I realized I could
 do something like this. Imagine doing this with C++ templates...  ugh!
 What a painful thought!)

If you actually want serialization, and this was not just an example, you can use Orange: https://github.com/jacob-carlborg/orange http://www.dsource.org/projects/orange/ -- /Jacob Carlborg
Mar 05 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-03-06 19:17, H. S. Teoh wrote:
 On Tue, Mar 06, 2012 at 08:17:07AM +0100, Jacob Carlborg wrote:
 On 2012-03-05 21:16, H. S. Teoh wrote:
 I know D doesn't really have RTTI yet, but I'm experimenting with
 "faking" it by doing something like:

 	class A {
 		string prop1;
 		int prop2;
 		...
 		void serialize() {
 			__serialize(this);
 		}
 	}

 	void __serialize(T)(T obj) {
 		writeln(typeid(obj));
 		foreach (name; __traits(derivedMembers, T)) {
 			writefln("%s = %s", name,
 				__traits(getMember,obj,name));
 		}
 	}


 If you actually want serialization, and this was not just an
 example, you can use Orange:

 https://github.com/jacob-carlborg/orange
 http://www.dsource.org/projects/orange/

For my purposes, I will eventually need to serialize only a subset of an object's properties, and only for a certain class of objects. Does Orange support selective serializations?

Yes, but by default is serializes everything you give it. Orange supports several ways of customizing the serialization. You can choose to not serialize specific fields or a whole class: class Foo { int a; int b; mixin NonSerialized!(b); // will not serialize "b" } class Foo { int a; int b; mixin NonSerialized; // will not serialize "Foo" at all } If you want to customize the serialization process in even more detail that's possible as well, by implementing the Serializable interface: class Foo : Serializable { int a; void toData (Serializer serializer, Serializer.Data key) { serializer.serialize(a, "b"); } void fromData (Serializer serializer, Serializer.Data key) { a = serializer.deserialize!(int)("b"); } } Actually, you don't need to implement the interface, it will use compile time introspection to check if the methods are available. Or the unintrusive approach: class Foo { int a; } auto dg = (Foo value, Serializer serializer, Serializer.Data key) { serializer.serialize(a, "b"); } Serializer.registerSerializer!(Foo)(dg); You can find the docs here: http://dl.dropbox.com/u/18386187/orange_docs/orange.serialization.Serializer.html In the docs, don't forget the "package" tab. -- /Jacob Carlborg
Mar 06 2012