www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Simulating reference variables using `alias this`

reply Carl Sturtivant <sturtivant gmail.com> writes:
Here's the beginning of an interesting little experiment to 
simulate reference variables using `alias this` to disguise a 
pointer as a reference. Could add a destructor to set the pointer 
to null when a reference goes out of scope.

```
struct reference(T)
{
     T* ptr;
     this(ref T x)
     {
         ptr = &x;
     }
     import std.exception : enforce;

     ref T cnvrt()  property
     {
         enforce( ptr !is null);
         return *ptr;
     }
     ref T cnvrt(T x)  property
     {
         enforce( ptr !is null);
         return *ptr = x;
     }
     alias cnvrt this;
}

void main()
{
     int i;
     auto ri = reference!int(i);
     auto ri2 = reference!int(ri);

     assert(ri.ptr==ri2.ptr);

     i = 99;
     assert(i==ri && i==ri2 && ri==ri2);

     ri = 100;
     assert(i==ri && i==ri2 && ri==ri2);

     ri2 = 101;
     assert(i==ri && i==ri2 && ri==ri2);
}
```
May 10
next sibling parent reply MrSmith <mrsmith33 yandex.ru> writes:
On Wednesday, 10 May 2017 at 17:12:11 UTC, Carl Sturtivant wrote:
 Here's the beginning of an interesting little experiment to 
 simulate reference variables using `alias this` to disguise a 
 pointer as a reference. Could add a destructor to set the 
 pointer to null when a reference goes out of scope.
 ...
I've used this code for similar purpose: alias TextEditorSettingsRef = TextEditorSettings*; alias TextEditorSettingsConstRef = const(TextEditorSettings)*; struct TextEditorSettings {} But you need to have two aliases (templates) for const and non-const refs, since using: const TextEditorSettingsRef editor; does: const(TextEditorSettings*) not const(TextEditorSettings)* What do you think?
May 10
parent Carl Sturtivant <sturtivant gmail.com> writes:
On Wednesday, 10 May 2017 at 17:48:53 UTC, MrSmith wrote:
 On Wednesday, 10 May 2017 at 17:12:11 UTC, Carl Sturtivant 
 wrote:
 Here's the beginning of an interesting little experiment to 
 simulate reference variables using `alias this` to disguise a 
 pointer as a reference. Could add a destructor to set the 
 pointer to null when a reference goes out of scope.
 ...
I've used this code for similar purpose: alias TextEditorSettingsRef = TextEditorSettings*; alias TextEditorSettingsConstRef = const(TextEditorSettings)*; struct TextEditorSettings {} But you need to have two aliases (templates) for const and non-const refs, since using: const TextEditorSettingsRef editor; does: const(TextEditorSettings*) not const(TextEditorSettings)* What do you think?
Works if you use new to get struct pointers. And . knows it's a pointer so you get the right effect. But I want to see if D can simulate general reference variables safely.
May 10
prev sibling parent Carl Sturtivant <sturtivant gmail.com> writes:
On Wednesday, 10 May 2017 at 17:12:11 UTC, Carl Sturtivant wrote:
 Here's the beginning of an interesting little experiment to 
 simulate reference variables using `alias this` to disguise a 
 pointer as a reference. Could add a destructor to set the 
 pointer to null when a reference goes out of scope.
Here's a better version. Improvements? This can still behave as badly as a pointer, e.g. if returned from a function. ``` struct reference(T) { T* ptr; this(ref T x) { ptr = &x; } ~this() { ptr = null; } import std.exception : enforce; ref T cnvrt() property { enforce( ptr !is null); return *ptr; } ref T cnvrt(T x) property { enforce( ptr !is null); return *ptr = x; } ref reference!T opAssign(T t) { enforce( ptr !is null); *ptr = t; return this; } ref reference!T opAssign(ref reference!T r) { enforce( ptr !is null && r.ptr !is null); *ptr = *r.ptr; return this; } alias cnvrt this; } void main() { int i; auto ri = reference!int(i); auto ri2 = reference!int(ri); assert(ri.ptr==ri2.ptr); i = 99; assert(i==ri && i==ri2 && ri==ri2); ri = 100; assert(i==ri && i==ri2 && ri==ri2); ri2 = 101; assert(i==ri && i==ri2 && ri==ri2); int j = -1; auto rj = reference!int(j); ri = rj; assert(ri==rj); assert(ri.ptr!=rj.ptr); } ```
May 10