dereferencing null

Chad J chadjoan at __spam.is.bad__gmail.com
Thu Mar 8 22:28:37 PST 2012


On 03/08/2012 10:40 AM, H. S. Teoh wrote:
> On Thu, Mar 08, 2012 at 02:57:00PM +0100, Andrej Mitrovic wrote:
>
>> I think what Chad is looking for is a BlackHole/WhiteHole equivalent
>> which doesn't need abstract functions but which figures out all the
>> methods of a class at compile time and creates a subclass that
>> throws/does nothing on method invocation. An 'alias this' field would
>> be used that is default-initialized with this sentry object. I don't
>> know why we don't have __traits(allFunction). We have
>> 'getVirtualFunctions' but it requires a function name, but using
>> allMembers to filter out function names is damn difficult if you ask
>> me. I've never had an easy time interacting with __traits.

Yep.  That would be cool.  Although there should be ways of doing the 
same thing for arrays and possibly even structs.  For structs I wouldn't 
mind adding a boolean field to keep track of its empty-or-not status.

>
> 	foreach (name; __traits(allMembers, typeof(obj))) {
> 		static if (__traits(compiles,&__traits(getMember, obj,
> 				name)))
> 		{
> 			alias typeof(__traits(getMember, obj, name))
> 				type;
> 			static if (is(type==function)) {
> 				// name refers to a function of type
> 				// 'type' here
> 			}
> 		}
> 	}
>
>> I've never had an easy time interacting with __traits.
>
> Me too. I'm guessing that __traits is the way it is due to ease of
> implementation in the compiler. It's certainly not very friendly to use.
>
>
> T
>

Tried this, but it wasn't picking everything up.

I also suspect that inheriting the class being wrapped and picking on 
its methods is going to be a losing battle in the long run for this 
thing.  It doesn't allow the sentry to throw on field access.  It also 
wouldn't work for final classes.  I wonder if opDispatch would do better.

Another mess I was running into was forwarding templated methods.  I 
wonder if this is even possible.  I wish __traits had some way of 
picking up on previous template instantiations (with cycles forbidden, 
of course).  If __traits were beefed up enough, maybe it would be better 
than opDispatch after all.  Hmmm.

I did try this as a struct with an "private T t; alias t this;" in it. 
It looks like this:

-----------------------------------

import std.c.stdlib;
import std.stdio;

struct Emptiable(T)
{
	private static Emptiable!T m_sentinel;
	// private NotNull!T t; // TODO
	private T t;
	
	alias t this;
	
	public static @property Emptiable!T sentinel()
	{
		return m_sentinel;
	}
	
	static this()
	{
		void* sentinelMem = malloc(T.sizeof);
		m_sentinel = cast(T)sentinelMem;
	}
	
	this(A...)(A args)
	{
		t = new T(args);
	}
	
	@property bool isEmpty() const
	{
		if ( this is m_sentinel )
			return true;
		else
			return false;
	}
}

static auto makeEmpty(T)(ref T v)
{
	v = T.sentinel;
	return v;
}

class Bar
{
	int i;
	
	this(int j) { i = j; }
	
	void blah()
	{
		writefln("blah!");
	}
	
	/+void letsTemplate(T)(T f)
	{
		writefln("%s",f);
	}+/
}

void main()
{
	auto bar = Emptiable!(Bar).sentinel;
	auto foo = new Emptiable!Bar(5);
	
	if ( bar.isEmpty )
		writefln("bar is empty, as it should be.");
	
	if ( !foo.isEmpty )
		writefln("foo is full, as it should be.");
	
	//foo.letsTemplate("Just a string.");
	
	writefln("foo.i is %s",foo.i);
	foo.i = 2;
	writefln("foo.i is %s",foo.i);
	
	/+
	makeEmpty(foo);
	if ( foo.isEmpty )
		writefln("foo is now empty.");
	writefln("foo.i is %s",foo.i);
	+/
}

-----------------------------------

Prints:
bar is empty, as it should be.
foo is full, as it should be.
foo.i is 5
foo.i is 2

-----------------------------------

It's super incomplete.  I am starting to realize that this sort of thing 
leads to a huge amount of weird corner cases.

Also note what happens when it tries to use makeEmpty: it fails because 
"auto foo = new Emptiable!Bar(5);" allocates an instance of the 
Emptiable struct on the heap, which then allocates a separate instance 
of Bar.  Yuck.  It's that old struct-vs-class construction schism again.



More information about the Digitalmars-d mailing list