www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Object Cast

reply "Namespace" <rswhite4 googlemail.com> writes:
To solve the problem of converting a Object to a specific 
template class i wrote this little function.
But the mixin disturbs me. How i can get the type (in this 
example Vector2D) without to mix a mixin and T.stringof?

[code]
T object_cast(T : Object)(Object value) {
	T val = cast(T) value;
	
	if (val !is null) {
		return val;
	}
	
	// if cast fails it is a template class
	
	import std.typetuple;
	
	foreach (Type; TypeTuple!(byte, ubyte, short, ushort, int, uint, 
long, ulong, float, double, real)) {
		mixin("
		if (auto vec = cast(" ~ T.stringof ~ "!(" ~ Type.stringof ~ 
"))(value)) {
			return cast(T) vec;
		}");
	}
	
	return null;
}
[/code]
Jun 21 2012
next sibling parent "Kenji Hara" <k.hara.pg gmail.com> writes:
On Thursday, 21 June 2012 at 10:33:41 UTC, Namespace wrote:
 To solve the problem of converting a Object to a specific 
 template class i wrote this little function.
 But the mixin disturbs me. How i can get the type (in this 
 example Vector2D) without to mix a mixin and T.stringof?

 [code]
 T object_cast(T : Object)(Object value) {
 	T val = cast(T) value;
 	
 	if (val !is null) {
 		return val;
 	}
 	
 	// if cast fails it is a template class
 	
 	import std.typetuple;
 	
 	foreach (Type; TypeTuple!(byte, ubyte, short, ushort, int, 
 uint, long, ulong, float, double, real)) {
 		mixin("
 		if (auto vec = cast(" ~ T.stringof ~ "!(" ~ Type.stringof ~ 
 "))(value)) {
 			return cast(T) vec;
 		}");
 	}
 	
 	return null;
 }
 [/code]

If you use 2.060head (git version), you can get template from the instantiated type. class Vec(T) {} void main() { alias Vec!int IntVec; static if (is(IntVec _unused : V!T, alias V, T)) { // V is class template Vec alias V!double DoubleVec; // another type instantiation test static assert(is(DoubleVec == Vec!double)); // equal! } else static assert(0); }
Jun 21 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
Works in dmd  2.059 too.

[code]
T template_cast(T : Object, U : Object)(U value) {
	// try to convert
	T val = cast(T) value;
	
	// if convert was successful, return
	if (val !is null) {
		return val;
	}
	
	// if cast fails it is a template class
     static if (is(T ClassType : V!W, alias V, W)) {
         // V is the template class
		import std.typetuple;
		
		// find out which one is "value"'s original type
		foreach (Type; TypeTuple!(byte, ubyte, short, ushort, int, 
uint, long, ulong, float, double, real)) {
			// if found: cast
			writeln(Type.stringof);
			if (auto vec = cast(V!Type) value) {
				return cast(Unqual!T) vec;
			}
		}
		
		return null;
     } else {
		return null;
	}
}
[/code]

Example:
[code]
class Rect(T) {
	T opCast(T : inout(Rect!U), U)() inout {
		return new T();
	}
	
	override string toString() const {
		return "Rect!(" ~ T.stringof ~ ")";
	}
}

void foo(Object o) {
	write("O ist: ");
	writeln(o);
	
	write("self cast: ");
	writeln(cast(Rect!int) o);
	
	write("template cast: ");
	Rect!int ri = template_cast!(Rect!int)(o);
	
	write("Result: ");
	writeln(ri);
}

Rect!(float) rf = new Rect!(float)();

foo(rf);
[/code]
Jun 21 2012
prev sibling next sibling parent "Kenji Hara" <k.hara.pg gmail.com> writes:
On Thursday, 21 June 2012 at 21:32:57 UTC, Namespace wrote:
 Works in dmd  2.059 too.

Oh, good.
 [code]
 T template_cast(T : Object, U : Object)(U value) {
 	// try to convert
 	T val = cast(T) value;
 	
 	// if convert was successful, return
 	if (val !is null) {
 		return val;
 	}
 	
 	// if cast fails it is a template class
     static if (is(T ClassType : V!W, alias V, W)) {
         // V is the template class
 		import std.typetuple;
 		
 		// find out which one is "value"'s original type
 		foreach (Type; TypeTuple!(byte, ubyte, short, ushort, int, 
 uint, long, ulong, float, double, real)) {
 			// if found: cast
 			writeln(Type.stringof);
 			if (auto vec = cast(V!Type) value) {
 				return cast(Unqual!T) vec;
 			}
 		}
 		
 		return null;
     } else {
 		return null;
 	}
 }
 [/code]

 Example:
 [code]
 class Rect(T) {
 	T opCast(T : inout(Rect!U), U)() inout {
 		return new T();
 	}
 	
 	override string toString() const {
 		return "Rect!(" ~ T.stringof ~ ")";
 	}
 }

 void foo(Object o) {
 	write("O ist: ");
 	writeln(o);
 	
 	write("self cast: ");
 	writeln(cast(Rect!int) o);
 	
 	write("template cast: ");
 	Rect!int ri = template_cast!(Rect!int)(o);
 	
 	write("Result: ");
 	writeln(ri);
 }

 Rect!(float) rf = new Rect!(float)();

 foo(rf);
 [/code]

Seems to me that you achieved the your first purpose. Do you need more help? Kenji Hara
Jun 21 2012
prev sibling parent "Namespace" <rswhite4 googlemail.com> writes:
 Seems to me that you achieved the your first purpose. Do you 
 need more help?

 Kenji Hara

I think i'm finished. Or have you any tip for me, related to the code?
Jun 22 2012