www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to make a transparent wrapper type?

reply Random D user <no email.com> writes:
I kind of miss reference values on stack, so I attempted to make 
one in a struct.
Pointers are pretty good (since d doesn't have ->), but it would 
be nice to avoid dereferencing them explicitly on assignment.

Since reference is a pointer that you can't change afterwards.
I tried something like this:

struct RefVal( T )
{
     this( T* val )                      {   ptr = val;  }

     ref auto opAssign( T value )        {   *ptr = value; return 
*ptr;  }
     ref auto opAssign( ref T value )    {   *ptr = value; return 
*ptr;  }

     alias ptr this;
     T* ptr;
}

This works for most basic cases but breaks in:

struct Foo
{
     this( int k )
     {
         a = k;
     }

     void opAssign( int k )
     {
         a = k;
     }

     int a;
}

Foo foo = Foo(2);
Foo baz = Foo(3);
RefVal!Foo bar = RefVal!Foo( &foo );

bar = baz;

bar = 5; // Ooops! doesn't work

Is there a way to transparently pass everything to *RefVal.ptr?

Also is there a way to make "alias ptr this" to work with 
"private T*"?
Ideally I wouldn't want to give access to the ptr, but for now 
it's handy as a workaround.
Dec 07 2015
parent reply Namespace <rswhite4 gmail.com> writes:
This seems to work:
----
struct RefVal(T) {
	private T* ptr;
	
     this(T* val) {
		ptr = val;
	}
	
     ref auto opAssign(U)(auto ref U value) {
		*ptr = value;
		
		return *ptr;
	}
	
	auto get() inout {
		return ptr;
	}
}
----
Dec 07 2015
parent reply Random D user <no email.com> writes:
On Monday, 7 December 2015 at 20:03:07 UTC, Namespace wrote:
 This seems to work:
 ----
 struct RefVal(T) {
 	private T* ptr;
 	
     this(T* val) {
 		ptr = val;
 	}
 	
     ref auto opAssign(U)(auto ref U value) {
 		*ptr = value;
 		
 		return *ptr;
 	}
 	
 	auto get() inout {
 		return ptr;
 	}
 }
 ----
Yes. It works for assignment as expected. Thanks. I don't know why I didn't try that. I mean I tried something like this: struct RefVal(T) { }
Dec 08 2015
parent Random D user <no email.com> writes:
On Tuesday, 8 December 2015 at 10:26:18 UTC, Random D user wrote:
 On Monday, 7 December 2015 at 20:03:07 UTC, Namespace wrote:
 This seems to work:
 ----
 struct RefVal(T) {
 	private T* ptr;
 	
     this(T* val) {
 		ptr = val;
 	}
 	
     ref auto opAssign(U)(auto ref U value) {
 		*ptr = value;
 		
 		return *ptr;
 	}
 	
 	auto get() inout {
 		return ptr;
 	}
 }
 ----
Yes. It works for assignment as expected. Thanks. I don't know why I didn't try that. I mean I tried something like this: struct RefVal(T) { }
Whoops. For some reason lost focus to window while typing and accidentally sent the message. Well. Anyway, I tried something similar using alias this and template functions, but obviously it didn't work. Unfortunately. Your version doesn't work with methods. For example if Ref!T is Ref!Struct then ref.method() doesn't work. That's the reason for alias this. But it's good enough with public ptr. Maybe opDispatch could help here. I haven't really used it so far.
Dec 08 2015