On Tuesday, 9 September 2025 at 01:24:59 UTC, monkyyy wrote:
```d
import std;
struct Vector(int N,T,string fields){
static foreach(I;0..N){
mixin("T "~fields[I]~";");
}
auto opDispatch(string __s__)(){//I suggest a habit of
avoiding simple names when generating mixin code
return mixin((){
string output="tuple(";
foreach(C;__s__){
output~=C;
output~=',';
}
output~=")";
return output;
}());
}
}
unittest{
Vector!(3,int,"xyz") foo;
foo.x=5;
foo.y=3;
foo.yx.writeln;
Vector!(4,ubyte,"rgba") bar;
bar.bgr.writeln;
}
```
I simplified your example, and manually expanded opDispatch so D
newbies can grok it.
Please explain the opDispatch IIFE and why no semicolon needed at
the end.
```
import std;
// Comment out yx() xor opDispatch()
struct Vector(int N, T, string fields){
int x;
int y;
int z;
// manual expansion of opDispatch
// auto yx() {
// string output = "tuple(";
// foreach (char scv; "yx") {
// output ~= scv;
// output ~= ",";
// }
// output ~= ")";
// writeln(output); // This is not in
opDispatch()
// return tuple(3, 5); // Hack to return same result
// }
// I suggest a habit of avoiding simple names when generating
mixin code
auto opDispatch(string __s__)() { // IIFE
writeln("__s__: ", __s__);
return mixin(() {
string output = "tuple(";
foreach (C; __s__){
output ~= C;
output ~= ',';
}
output ~= ")";
return output;
} ());
}
}
void main() {
Vector!(3, int, "xyz") foo;
foo.x = 5; // Standard assignment to known member
foo.y = 3; // Standard assignment to known member
foo.yx.writeln; // yx not a member of Vector, so opDispatch is
called
}}
```
Console output:
```
__s__: yx
Tuple!(int, int)(3, 5)
```