Nested Structs (Solution)

js.mdnq js_adddot+mdng at gmail.com
Wed Dec 12 14:16:19 PST 2012


Here is a solution I came up with that seems to work fine and 
does not require hard coding any values. Hence, it is useable. 
Unfortunately it looks clunky and is: (and it would be nice to 
speed up the the method call and possible code it in such a way 
that if D directly supports this in the future it will be easy to 
update)


http://dpaste.dzfl.pl/64025e0a


The idea is rather simple: We pass the offset of the struct 
object to itself as a template parameter. This allows the struct 
to calculate where it is at relative to the parent, which then 
allows it to access the members of the parent. This is quite easy 
to do and no issue. (except, of course, copying the struct will 
potentially invalidate it's parent)

The problem is actually calculating the offsets of these structs 
in the class(which are passed to the struct). Hard coding is a no 
go and using offsetof will not work because of forward 
referencing(you need to know the size of the type to find out the 
offsets

To do this, kinda hackish, but works, is we template the class 
containing the structs. This allows us to conditionally create 
the class. A!0, creates a class that we can then use to get the 
offsets. The forward references are no longer since we use A!0 
which passes dummy offsets to the structs. A!x, for x > 0, then 
calculates the offsets of the structs using A!0 as a blueprint. 
A!0 has no offsetof so no forward referencing. A!1 uses offsetof 
for A!0, so, again, no forward referencing. Since passing offsets 
do not change the size we should expect A!1 to have the layout as 
A!0.

The "trick" here is:

static if (dummy == 0) B!(0) b1; else  B!(A.b1.offsetof) b1;


As you can see in the code, it's quite messy and ideally should 
look like a normal nested struct inside a class without any 
template parameters being used.

I'm hoping someone can come up with an elegant way to wrap this 
neatly into a package that can be used as any normal nested 
struct, or close.

Thanks...














Code:

module main;

import std.stdio;




class cAt(int dummy)
{
	alias cAt!0 A;
	struct B(int ofs)  {
		int Value;
		A Parent()
		{
			auto p = cast(void *)&this - ofs;
			return cast(A)(p);
		}		
	}

	static if (dummy == 0) B!(0) b1; else  B!(A.b1.offsetof) b1;
	static if (dummy == 0) B!(0) b2; else  B!(A.b2.offsetof) b2;

	string Name;

	this()
	{
		Name = "Class";
	}
}
alias cAt!1 A;

int main(string[] argv)
{
	

	auto asize = A.classinfo.init.length;
	auto bsize = A.B!(0).sizeof;
	A a = new A();
	auto x = a.b1.Parent();
	auto y = a.b2.Parent();
	
	auto s1 = A.init.b1.offsetof;
	auto s2 = A.init.b2.offsetof;

	auto a_ptr = cast(void*)a;
	auto x_ptr = cast(void*)x;
	auto y_ptr = cast(void*)y;

	assert(a_ptr == x_ptr);
	assert(x_ptr == y_ptr);

	getchar();
	return 0;
}


More information about the Digitalmars-d mailing list