Ref / NotNull struct

Namespace rswhite4 at googlemail.com
Sun May 6 02:41:24 PDT 2012


I like to present my version of an NotNull Reference struct.
Two Bugs with "alias this" caused me a lot of trouble and one of 
them (the recursive infinite loop) i cannot fix by myself. 
Because of that you have to access the object in the struct with 
"obj.access" instead of "obj".
Little Example:
[code]
class A {
     // these mixin template contains the functionality to convert 
"A" to "Ref!(A)"
     mixin TRef!(A);

     void say_something() const {
         writeln("Hello");
     }
}

void foo(Ref!(A) ra) {
     // don't work until yet
     // ra.say();
     // so you have to write
     ra.access.say();
}

In my opinion a little annoying but i hope this bug will be fixed 
soon.
I think the reason for this behaviour is simple: if you have two 
structs/classes wich convert each to another and mark these 
convert methods with "alias this" the compiler found no solution 
and turns into an ininite loop. That could explain the 
"Stackoverflow" after compiling.
Or isn't that a real bug?

Well, here is the code:

[code]
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 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 {
		return *(cast(U*) &this);
	}

	alias getRef this;
}
[/code]

I'm using this construct already in one of my university projects 
and until now i found no errors. But for completeness: here the 
code of my test module: http://codepad.org/XGp3APCt

I would be glad for criticism and suggestions and maybe a 
solution/workaround for the infinite loop bug, if it's the case, 
that it's really a bug.


More information about the Digitalmars-d-learn mailing list