From the D Blog: (Ab)using Overload Sets to Create Ad-Hoc Template APIs

jmh530 john.michael.hall at gmail.com
Wed Jul 22 13:32:17 UTC 2026


On Wednesday, 22 July 2026 at 13:14:50 UTC, jmh530 wrote:
> 
>> Kinda hard to think of a case like that.
>> If you have two of those in the same scope then that would be 
>> a bit annoying. Avoiding the alias `GVec2` and using the new 
>> version directly would help. So you use `GVec2` for the old 
>> one and `GVec!(float, 2)` for the new one.
>
> See my reply to monkeyyy [1], if you have the aliases, it 
> doesn't compile.
>
> What you actually have to do is remove the aliases and do 
> something like this
> [snip]

Eh, that's just re-using the original type. You can replace it 
with GVec!(2, int), although you need to add constructors to make 
it more convenient. I tried a three file version, but I wasn't 
able to confirm with run.dlang.io that this works. It's not 
liking using three separate files. But I think it would work.

```d
--- test.d
import gvec_v2;

alias GVec2(T = float) = GVec!(2, T);
alias GVec3(T = float) = GVec!(3, T);
alias GVec4(T = float) = GVec!(4, T);

void main()
{
     GVec2!int x = GVec2!int(1, 2);
     foo(x);
}
--- gvec_v2.d
public import gvec: foo;

struct GVec(int N : 2, T) {
     import gvec: GVec2;
     GVec2!T _data;
     alias _data this;
     this(T x, T y) { _data.x = x; _data.y = y;}
}
struct GVec(int N : 3, T) {
     import gvec: GVec3;
     GVec3!T _data;
     alias _data this;
     this(T x, T y, T z) { _data.x = x; _data.y = y; _data.z = z;}
}
struct GVec(int N : 4, T) {
     import gvec: GVec4;
     GVec4!T _data;
     alias _data this;
     this(T x, T y, T z, T w) { _data.x = x; _data.y = y; _data.z 
= z; _data.w = w;}
}
--- gvec.d
import std.stdio: writeln;

struct GVec2(T) { T x, y; }
struct GVec3(T) { T x, y, z; }
struct GVec4(T) { T x, y, z, w; }

void foo(GVec2!int x) {
     writeln(x.x);
     writeln(x.y);
}
```


More information about the Digitalmars-d-announce mailing list