Returning a reference to be manipulated

IchorDev zxinsworld at gmail.com
Thu Apr 13 16:10:14 UTC 2023


On Thursday, 13 April 2023 at 07:05:10 UTC, Chris Katko wrote:
> I'm trying to figure out how to return a reference to something 
> that may not be a reference type.
>
> ```D
> struct stats
> {
> float[string] data=0;
>
> float ref opIndex(string key)
>   {
>   return data[key]; // want a ref to a specific element
>   }
> }
>
> void test()
> {
> stats foo;
> auto x = foo.bar(); // returns some sort of reference
>        // data["tacos"] = 0
> x++;   // data["tacos"] = 1
> }
> ```
>
> Right now, I'm using pointers which resolves to:
>
> ```D
> // float* opIndex(string key){...} using pointer
> (*s["tacos"])++; // works with pointer, but is strange looking
>
> s["tacos"]++; // preferred syntax or something similar
> ```

I'm pretty sure you can't return `ref` to a value-type without it 
being a pointer, or a slice.
Unlike C++, D does not have `ref` variables (`&`). You can have 
value-type function parameters that are `ref` though.
But I feel that the easier solution for the example you gave 
would be to simply save the string used to index the float, 
rather than a reference to the float itself:

```d
import std.stdio: writeln;

struct Stats{
	float[string] data;
	
	float opIndex(string key){ return data[key]; }
	float opIndexAssign(float val, string key){ data[key] = val; 
return val; }
}

void main(){
	Stats foo;
	foo.data = ["tacos": 0];
	
	string ind = "tacos";
	float x = foo[ind];
	writeln(foo.data[ind]); //0
	x++;
	foo[ind] = x;
	writeln(foo.data[ind]); //1
}
```

Passing pointers around might be faster, but it's error-prone, 
and cumbersome for simple operators as you mentioned. However, 
you could always wrap your pointer in a struct with some 
necessary operator overloads:
```d
import std.stdio: writeln;

struct Float{
	float* data;
	
	float opUnary(string op: "++")(){ (*data)++; return *data; }
}

struct Stats{
	float[string] data;
	
	Float opIndex(string key){ return Float(key in data); }
}

void main(){
	Stats foo;
	foo.data = ["tacos": 0];
	
	Float x = foo["tacos"];
	writeln(foo.data["tacos"]); //0
	x++;
	writeln(foo.data["tacos"]); //1
}
```


More information about the Digitalmars-d-learn mailing list