smart pointer for interior pointers
Artur Skawina via Digitalmars-d
digitalmars-d at puremagic.com
Wed May 27 17:21:35 PDT 2015
On 05/28/15 01:31, Steven Schveighoffer via Digitalmars-d wrote:
> 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:
It doesn't.
S f() { return S(42); }
> 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.
auto a = s.y;
// this 'a' now implicitly converts to 'int', but...
void g(T)(T a);
g(s.y); // ditto.
artur
More information about the Digitalmars-d
mailing list