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
}
```