On Saturday, 14 August 2021 at 20:50:47 UTC, Carl Sturtivant wrote:
> struct S {
int x = 1234;
}
void main() {
import std.stdio;
S s;
//construction of a using &(s.x)
auto a = Ref!(int)(&s.x);
writeln(a); //displays 1234
s.x += 1;
writeln(a); //displays 1235
a += 1;
writeln(s.x); //displays 1236
}
struct Ref(T) {
T* ptr;
this(T* p) { ptr = p; }
string toString() { import std.conv; return to!string(*ptr); }
ref T var() { return *ptr; }
alias var this;
}
Hi,
This is exactly the behaviour I was trying to obtain.
It however comes with a fair amount of overhead, as can be seen in the following llvm ir:
define i32 @_Dmain({ i64, { i64, i8* }* } %unnamed) #0 {
%s = alloca %onlineapp.S, align 4 ; [#uses = 4, size/byte = 4]
%a = alloca %"onlineapp.Ref!int.Ref", align 8 ; [#uses = 5, size/byte = 8]
%1 = bitcast %onlineapp.S* %s to i8* ; [#uses = 1]
call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %1, i8* align 1 bitcast (%onlineapp.S* @onlineapp.S.__init to i8*), i64 4, i1 false)
%2 = bitcast %"onlineapp.Ref!int.Ref"* %a to i8* ; [#uses = 1]
call void @llvm.memset.p0i8.i64(i8* align 1 %2, i8 0, i64 8, i1 false)
%3 = getelementptr inbounds %onlineapp.S, %onlineapp.S* %s, i32 0, i32 0 ; [#uses = 1, type = i32*]
%4 = call %"onlineapp.Ref!int.Ref"* @pure nothrow ref @nogc @safe onlineapp.Ref!(int).Ref onlineapp.Ref!(int).Ref.__ctor(int*)(%"onlineapp.Ref!int.Ref"* nonnull returned %a, i32* %3) #4 ; [#uses = 0]
%5 = load %"onlineapp.Ref!int.Ref", %"onlineapp.Ref!int.Ref"* %a, align 8 ; [#uses = 1]
call void @@safe void std.stdio.writeln!(onlineapp.Ref!(int).Ref).writeln(onlineapp.Ref!(int).Ref)(%"onlineapp.Ref!int.Ref" %5) #4
%6 = getelementptr inbounds %onlineapp.S, %onlineapp.S* %s, i32 0, i32 0 ; [#uses = 2, type = i32*]
%7 = load i32, i32* %6, align 4 ; [#uses = 1]
%8 = add i32 %7, 1 ; [#uses = 1]
store i32 %8, i32* %6, align 4
%9 = load %"onlineapp.Ref!int.Ref", %"onlineapp.Ref!int.Ref"* %a, align 8 ; [#uses = 1]
call void @@safe void std.stdio.writeln!(onlineapp.Ref!(int).Ref).writeln(onlineapp.Ref!(int).Ref)(%"onlineapp.Ref!int.Ref" %9) #4
%10 = call i32* @pure nothrow ref @nogc @safe int onlineapp.Ref!(int).Ref.var()(%"onlineapp.Ref!int.Ref"* nonnull %a) #4 ; [#uses = 2]
%11 = load i32, i32* %10, align 4 ; [#uses = 1]
%12 = add i32 %11, 1 ; [#uses = 1]
store i32 %12, i32* %10, align 4
%13 = getelementptr inbounds %onlineapp.S, %onlineapp.S* %s, i32 0, i32 0 ; [#uses = 1, type = i32*]
%14 = load i32, i32* %13, align 4 ; [#uses = 1]
call void @@safe void std.stdio.writeln!(int).writeln(int)(i32 %14) #4
ret i32 0
}