Balagopal Komarath <baluks gmail.com> writes:
```Is there a way to avoid the following combinatorial explosion of
arguments? The following may be a bad example because int is
cheap to copy. So assume a large datatype instead of int.

import std.stdio;

void foo(in ref int a, in ref int b)
{
writeln("r, r");
}

void foo(in ref int a, in int b)
{
writeln("r, i");
}

void foo(in int a, in ref int b)
{
writeln("i, r");
}

void foo(in int a, in int b)
{
writeln("i, i");
}

void main()
{
int a, b;
foo(a, b);
foo(a, 0);
foo(0, a);
foo(0, 0);
}
```
Jun 12 2017
Jonathan M Davis via Digitalmars-d-learn writes:
```On Monday, June 12, 2017 20:40:52 Balagopal Komarath via Digitalmars-d-learn
wrote:
Is there a way to avoid the following combinatorial explosion of
arguments? The following may be a bad example because int is
cheap to copy. So assume a large datatype instead of int.

import std.stdio;

void foo(in ref int a, in ref int b)
{
writeln("r, r");
}

void foo(in ref int a, in int b)
{
writeln("r, i");
}

void foo(in int a, in ref int b)
{
writeln("i, r");
}

void foo(in int a, in int b)
{
writeln("i, i");
}

void main()
{
int a, b;
foo(a, b);
foo(a, 0);
foo(0, a);
foo(0, 0);
}

If you templatize the function, you can use auto ref. e.g.

void foo(T)(auto ref T a) {..}

or

void foo()(auto ref int a) {...}

and then when the function is instantiated, the instantiation will be ref or
non-ref depending on whether an lvalue or rvalue was passed. So you still
get the combinatorial explosion of functions, but you don't have to write
them manually. Of course, if you're dealing with a virtual function though,
you'll have to do it manually, because templated functions can't be virtual.
But in cases like that, you could have a protected function which took ref
and a public, templated, wrapper function that took auto ref so that you
don't have to do it all manually.

In general though, I'd suggest just not using ref to avoid copying unless
you know that it's a performance problem.

- Jonathan M Davis
```
Jun 12 2017