smart pointer for interior pointers
Steven Schveighoffer via Digitalmars-d
digitalmars-d at puremagic.com
Wed May 27 16:31:32 PDT 2015
I just was working on a project, and I had a need for two members of a
struct to share state.
How could this work? A simple example:
struct S
{
int x;
int *y; // should refer to x
this(int v)
{
x = v;
y = &x;
}
}
But this doesn't work on copying, because when you copy S, S.y is still
pointing at the OLD S. Example:
S s1 = S(5);
S s2 = s1;
s1.x = 4;
writeln(*s2.y); // oops, writes 4, because s2.y is pointing at s1.x, not
s2.x
But we can solve this with a postblit:
this(this) { y = &x;}
Although this works, there are issues:
1. y's target is defined by the type, it's impossible to rebind y at
runtime, without having a copy mess that up.
2. Copying still requires executing a function to fixup the pointer.
3. Even if y's relative target isn't supposed to change, S has to know
where to point y at relative to itself! For example, if S was inside a
struct like this:
struct S2
{
S s;
int y; // I really want s.x to point at *this* y
}
Now, you need to add a postblit to S2 as well.
But with alias this, we can define a way to solve all these problems.
struct SPtr(T)
{
ptrdiff_t _offset;
void opAssign(T *orig) { _offset = cast(void *)orig - cast(void
*)&this;}
inout(T) *_get() inout { return cast(inout(T)*)((cast(inout(void)
*)&this) + _offset);}
alias _get this;
}
Basically, instead of storing the pointer, we store the offset to the
struct itself. This works as long as the SPtr instance stays co-located
with its target.
It has some advantages:
1. It can be defined at compile/initialization time:
struct S
{
int x;
SPtr!int y = SPtr(offsetFromytox); // not sure of an easy way to
autocreate the offset :)
}
2. You can copy S anywhere, and every instance's y will point at the
instance's x, without running any fixup code. You can even use memcpy.
The disadvantage, and I think there's only one, is that using SPtr must
perform math that a straight pointer will not. I think in cases where
this is needed, I prefer this disadvantage over the ones of other choices.
Thoughts? Does this seem like a good candidate for std.typecons?
If so, what's a good name? I want something kind of short :)
-Steve
More information about the Digitalmars-d
mailing list