Explict Overload Sets

With (hopefully) an understanding of how overload sets one of the most fundmental concepts in the compiler. What do I suggest you do with it?

Specailization, lots and lots of specailization.

int foo(T:int)()=>1;
int foo(T:float)()=>2;
static assert(foo!float==2);

Foo when initualized can look up a value here. But remember last chapter, foo can be passed around and everything is an overload set; these could easily be types, functions, or other templates.

But most realisticly, an hacky "ct type array":

alias foo(int I:0)=int;
alias foo(int I:1)=float;
static foreach(I;0..2){
	pragma(msg,foo!I.stringof);
}

Ive had an argument with kap resently(basicly nearly a fist fight >:( ) about the radical importance of templates, the anti-template extermist claimed "(T) > (int N,T)" if you can believe it. (I couldnt I was shocked by the ignorence)

He pointed at his own code: https://github.com/Kapendev/joka/blob/main/source/joka/math.d

alias BVec2 = GVec2!byte;   /// A 2D vector using bytes.
alias IVec2 = GVec2!int;    /// A 2D vector using ints.
alias UVec2 = GVec2!uint;   /// A 2D vector using uints.
alias Vec2 = GVec2!float;   /// A 2D vector using floats.
alias DVec2 = GVec2!double; /// A 2D vector using doubles.

alias BVec3 = GVec3!byte;   /// A 3D vector using bytes.
...

alias BVec4 = GVec4!byte;   /// A 4D vector using bytes.
...

/// A generic 2D vector.
struct GVec2(T) {
	T x = 0; /// The X component of the vector.
	T y = 0; /// The Y component of the vector.
	...

/// A generic 3D vector.
struct GVec3(T) {
	T x = 0; /// The X component of the vector.
	T y = 0; /// The Y component of the vector.
	T z = 0; /// The Z component of the vector.
	...
...

I tried, in vain, to explain that he should just define all three reasonable ways to access the types.... but I disgess.

He seemed to think it was nessery to define a super vec template in some awful hellscape of meta programming and 500 lines of hard to untangle code. This isnt true. You need to define a single overload set but it is not nessery to make that a single template.

Consider this rewrite of the headers:

/// A generic 2D vector.
alias GVec2(T=float)=GVec!(2,T);
struct GVec(int N:2,T) {
	T x = 0; /// The X component of the vector.
	T y = 0; /// The Y component of the vector.
}
/// A generic 3D vector.
alias GVec3(T=float)=GVec!(3,T);
struct GVec(int N:3,T) {
	T x = 0; /// The X component of the vector.
	T y = 0; /// The Y component of the vector.
	T z = 0; /// The Z component of the vector.
}
alias GVec4(T=float)=GVec!(4,T);
struct GVec(int N:4,T) {
	T x = 0; /// The X component of the vector.
	T y = 0; /// The Y component of the vector.
	T z = 0; /// The Z component of the vector.
	T w = 0; /// The W component of the vector.
}

Suddenly GVec is one overload set and (in thoery) doesnt change any of his other code.

This will allow users to define meta programming over the vec's:

void print(int N,T)(GVec!(N,T) bar){
	import std;
	writeln("this is a vector of ",N," ",T.stringof);
	static foreach(C;"xyzw"[0..N]){
		writeln(C,":",mixin("bar."~C));
}}
unittest{
	IVec3(1,4,7).print;
	DVec4(2,6,0,0).print;
}
this is a vector of 3 int
x:1
y:4
z:7
this is a vector of 4 double
x:2
y:6
z:0
w:0

and we could keep going :D

code