[ create a new paste ] login | about

Link: http://codepad.org/lfxe5plJ    [ raw code | fork ]

D, pasted on May 6:
import std.stdio, std.typecons;
import std.conv : to;

template CreateMsg(string msg, string file = __FILE__, size_t line = __LINE__) {
	enum CreateMsg = msg ~  " @ " ~ file ~ " in Line " ~ to!(string)(line) ~ ".";
}

string CreateErrorMsg(string msg, string file = __FILE__, size_t line = __LINE__) {
	return msg ~  " @ " ~ file ~ " in Line " ~ to!(string)(line) ~ ".";
}

struct Ref(T : Object) {
private:
	 T _obj;

public:
	@disable
	this();

	@disable
	this(typeof(null));

	this(T obj) {
		assert(obj !is null, CreateMsg!("Object is null!"));

		this._obj = obj;
	}

	@disable
	typeof(this) opAssign()(typeof(null));

	typeof(this) opAssign(U : T)(Ref!(U) refer) {
		this._obj = refer.access;

		return this;
	}
	
	typeof(this) opAssign(U : T)(U refer) {
		assert(refer !is null, CreateMsg!("Object is null"));

		this._obj = refer;

		return this;
	}
	
	@property
	inout(T) access() inout {
		assert(this._obj !is null, CreateMsg!("Access: Object is null!"));

		return this._obj;
	}

	// DMD Bug: The compiler creates and infinite loop.
	// if uncomment, the compiler print "Stackoverflow" or "recursive expansion"
	//alias access this;

	mixin Proxy!(this._obj);
}

mixin template TRef(T : Object) {
	final Ref!(T) getRef(string file = __FILE__, size_t line = __LINE__) in {
		assert(this !is null, CreateErrorMsg("Object is null!", file, line));
	} body {
		return Ref!(T)(this);
	}
	
	final Ref!(const T) getRef(string file = __FILE__, size_t line = __LINE__) const in {
		assert(this !is null, CreateErrorMsg("Object is null!", file, line));
	} body {
		return Ref!(const T)(this);
	}
	
	// Hack for Bug 8001 (http://forum.dlang.org/thread/bug-8001-3@http.d.puremagic.com%2Fissues%2F)
	U opCast(U/* : Object*/)() inout {
		writeln(typeid(U));
		return *(cast(U*) &this);
	}
	
	alias getRef this;
}

class Foo {
public:
	void say() const {
		writeln("Hallo");
	}
	
	mixin TRef!(Foo);
}

void normal_foo(Foo f) {
	f.say();
}

void ref_foo(Ref!(Foo) rf) {
	rf.say();
}

T const_cast(T : Object)(const T obj) {
	return cast(T) obj;
}

void main() {
	Foo f1 = new Foo();
	
	normal_foo(f1);
	ref_foo(f1);
	
	Ref!(Foo) rf1 = new Foo();
	
	normal_foo(rf1);
	ref_foo(rf1);
	
	bool instanceof(T : Object, U : Object)(const Ref!(U) obj) {
		const U o = obj.access;
		
		return const_cast(o).toString() == typeid(T).toString();
	}
	
	class A {
		mixin TRef!(A);
	}

	class B : A {
		mixin TRef!(B);
	}

	class C : B {
		mixin TRef!(C);
	}

	A a1 = new B();
	A a2 = new C();
	
	assert(instanceof!(A)(a1) == false);
	assert(instanceof!(B)(a1));
	assert(instanceof!(C)(a1) == false);
	
	writeln(a1);

	B b1 = cast(B) a1;

	assert(instanceof!(A)(b1) == false);

	writeln(b1);

	writeln("---");
}


Create a new paste based on this one


Comments: