What one might want to do:
struct X
{
this(int x) { … } // 1
this(int y) { … } // 2
}
void main()
{
X(x: 1); // call 1
X(y: 2); // call 2
}
Of course, that doesn’t work. Parameter names aren’t part of the function signature and therefore, the two constructors clash. It’s not an ambiguity error on the call-site, it’s just that the two constructors have the same mangle.
However, I found a neat trick how it can be done. For each problematic overload, add an enum type with one value:
enum f_x_t { value }
enum f_y_t { value }
Then, change each overload so that it takes a value of the respective enum type as their first parameter, defaulted to the obvious value:
struct X
{
this(f_x_t = f_x_t.value, int x) { … } // 1
this(f_y_t = f_y_t.value, int y) { … } // 2
}
Then, the two constructors have different mangles and can be distinguished in the object file. In code, using named arguments, one can re-order the parameters and because the enum parameters are defaulted, they need no arguments.
import std.stdio;
struct X
{
private enum f_x_t { value }
private enum f_y_t { value }
this(f_x_t = f_x_t.value, int x) { writeln("X(int x) called with ", x); }
this(f_y_t = f_y_t.value, int y) { writeln("X(int y) called with ", y); }
}
void main()
{
X(x: 1); // X(int x) called with 1
X(y: 2); // X(int y) called with 2
}
For ordinary functions, the following works as well:
void f_x(int x) { writeln("f(int x) called with ", x); }
void f_y(int y) { writeln("f(int y) called with ", y); }
alias f = f_x;
alias f = f_y;
The only downside is that it does not work for constructors, possibly among others.