www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Overloading based on named arguments is possible,

reply Quirin Schroll <qs.il.paperinik gmail.com> writes:
What one might want to do:
```d
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:
```d
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:
```d
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.
```d
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:
```d
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.
May 07
parent reply cc <cc nevernet.com> writes:
On Tuesday, 7 May 2024 at 11:58:59 UTC, Quirin Schroll wrote:
 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.
Interesting! Looks like this can be done via template arguments as well. ```d struct X { this(string f = "x")(int x) { writeln("X(int x) called with ", x); } this(string f = "y")(int y) { writeln("X(int y) called with ", y); } } X(x: 1); // X(int x) called with 1 X(y: 2); // X(int y) called with 2 ```
May 07
parent Martin Tschierschke <mt smartdolphin.de> writes:
On Wednesday, 8 May 2024 at 04:46:26 UTC, cc wrote:
[...]
 X(x: 1); // X(int x) called with 1
 X(y: 2); // X(int y) called with 2
 ```
Cool!
May 08