## digitalmars.D.learn - cross_module function overloading & alias & template: how to ?

Picaud Vincent <picaud.vincent gmail.com> writes:
```Hi All,

In my adventure to learn a little bit of D coming from C++ I am
now faced with the following problem:

Andrei Alexandrescu book.
That makes sense to me and this is interesting.

As a concrete example here the scenario: I want to define a
specialized version of the min function.

In D knowing that if there is an ambiguity between modules the
compiler generates an error, the following example does NOT work:

==========================================

// I am the my_min.d file
module my_min;

int min(int a,int b)
{
return (a<b) ? a : b;
}

==========================================

// I am the app.d file
import std.algorithm.comparison;
import my_min;

void main()
{
int a=1,b=2;
auto c=min(a,b);      // Compile-time ERROR!
// my_min.min at source/my_min.d:7:5
conflicts with
// std.algorithm.comparison.min!(int,
int).min
auto dc=min(4.5,b);   // OK (no ambiguity)
}

==========================================

The D solution is to use the keyword "alias" :

==========================================

// I am the my_min.d file
module my_min;
import std.algorithm.comparison;

int min(int a,int b)
{
return (a<b) ? a : b;
}

alias std.algorithm.comparison.min min; // Here is the magic that
imports
// std min declaration
into my_min module
// and allows "global"
// to take place here, in
my_min module

==========================================

// I am the app.d file
import my_min;
// <- ATTENTION DO NOT RE-import std.algorithm.comparison HERE!

void main()
{
int a=1,b=2;
auto c=min(a,b);     // OK! -> use my_min.min
auto dc=min(4.5,b);  // OK! -> use std.algorithm.comparison.min
}

==========================================

But now I have the following problem: if I use a parametrized
function min:

==========================================

module my_min;
import std.algorithm.comparison;

T min(T)(T a,T b)
{
return (a<b) ? a : b;
}

alias std.algorithm.comparison.min min; // <- Does NOT compile
anymore
// error: alias my_min.min conflicts with template
my_min.min(T)(T a, T b)

==========================================

-------> What am I missing? What is the right way to do that?

Thank you :)
```
Nov 10 2016
Jonathan M Davis via Digitalmars-d-learn writes:
```On Thursday, November 10, 2016 15:46:11 Picaud Vincent via Digitalmars-d-
learn wrote:
-------> What am I missing? What is the right way to do that?

Honestly, I'm surprised that the compiler let you alias
std.algorithm.comparison.min, because it's a templated function, and in the
case of templates, you alias instantiations of templates, not the templates
themselves. std.algorithm.comparison.min is just a template for a function,
not an actual function. Something like
std.algorithm.comparison.min!(int, int) would be an actual function.

But even if the compiler lets you alias std.algorithm.comparison.min, the
min and the one in std.algorithm is that yours is non-templated, and
Once they're both templates, the only way to distinguish is their template
constraints and the number of arguments.

T min(T)(T a, T b)
{
return a < b ? a : b;
}

has no template constraint. It matches every call to it where there are two
arguments of the same type. Its internals may not compile with every type,
but the overload resolution doesn't care about that. So, without a template
constraint that distinguishes your min from std.algorithm's min, there's no
way that it's going to work. And it's not actually _possible_ for you to
declare a template constraint that makes your min match and not
std.algorithm's min. For starters, you seem to be trying to pass it
arguments which obviously work with std.algorith's min. So, by definition,
you cannot possibly create something that overloads with it and does what
you want. The only way that it would make sense to overload with
std.algorithm's min would be if your min accepted arguments that
std.algorithm's min didn't, and it doesn't sound like that's what you're
trying to do. But perhaps more importantly if you actually look at
std.algorithm.comparison.min's template constraint

MinType!T min(T...)(T args)
if (T.length >= 2)
{
...
}

you'll see that it basically matches _everything_, pretty much like yours
does. Its only restriction is that there have to be at least two arguments.
It doesn't even have anything in the constraint to make sure that the
arguments are comparable. It does that with a static assertion internally.

So, the _only_ way to overload with std.algorithm's min is by declaring a
non-templated function so that std.alorgithm's templated min function isn't
even considered. If you want to have a min function that does something
different and still be able to call std.algorithm's min, then you're going
to need to wrap std.algorithm's min. e.g something like

T min(T)(T a, T b)
{
static if(some condition that makes it want to use your min)
{
return a < b ? a : b;
}
else
{
import std.algorithm.comparison : min;
return min(a, b);
}
}

With a function like min though, I would think that it would be better to
just use std.algorithm's min, and if you wanted to do something different
with yours to just declare a function with a different name. After all, it's
pretty standard what min does, so if yours is doing anything different, then
it should probably have a different name, and if it does the same thing,
then there's no point in having it.

picked a very poor function to do that with, because
std.algorithm.comparison.min matches basically everything. If you want to
overload a function, then you really need to be picking one that has stuff
that it doesn't accept that you can then declare a function that accepts.

- Jonathan M Davis
```
Nov 10 2016
Picaud Vincent <picaud.vincent gmail.com> writes:
```On Thursday, 10 November 2016 at 17:12:32 UTC, Jonathan M Davis
wrote:
On Thursday, November 10, 2016 15:46:11 Picaud Vincent via
Digitalmars-d- learn wrote:
[...]

Honestly, I'm surprised that the compiler let you alias
std.algorithm.comparison.min, because it's a templated
function, and in the
case of templates, you alias instantiations of templates, not
the templates
themselves. std.algorithm.comparison.min is just a template for
a function,
not an actual function. Something like
std.algorithm.comparison.min!(int, int) would be an actual
function.

[...]

Hi Jonathan,

Unfortunately I have not the time right now to answer (I am
leaving my job it is 6:53PM).
However I just created a github repo to reproduce my observations:

It is certainly a compiler problem: I used gdc -> compile error,
but with dmd it compiles and runs fine. Full details in the git
repo.

More answers later... I have to leave
```
Nov 10 2016
Jonathan M Davis via Digitalmars-d-learn writes:
```On Thursday, November 10, 2016 17:41:02 Picaud Vincent via Digitalmars-d-
learn wrote:
It is certainly a compiler problem: I used gdc -> compile error,
but with dmd it compiles and runs fine. Full details in the git
repo.

Don't bother with gdc at this point. Unless there's a development version of
it that's actually up-to-date and hasn't been released yet, it's too old to
be reliable with regards to what correct D is. If something doesn't work in
gdc, it could easily be because of a bug that has since been fixed.
Unfortunately, the gdc folks have never managed to release an updated gdc
that uses the D version of the compiler front-end, so as I understand it,
they're still stuck at 2.067 (which is over 2 years old), whereas dmd is now
at 2.072. ldc should be reasonably up-to-date if you want an alternative to
dmd, and I expect that the gdc guys will get there eventually, but they
haven't yet.

- Jonathan M Davis
```
Nov 10 2016
Picaud Vincent <picaud.vincent gmail.com> writes:
```On Thursday, 10 November 2016 at 20:12:10 UTC, Jonathan M Davis
wrote:
On Thursday, November 10, 2016 17:41:02 Picaud Vincent via
Digitalmars-d- learn wrote:
It is certainly a compiler problem: I used gdc -> compile
error, but with dmd it compiles and runs fine. Full details in
the git repo.

Don't bother with gdc at this point. Unless there's a
development version of it that's actually up-to-date and hasn't
been released yet, it's too old to be reliable with regards to
what correct D is. If something doesn't work in gdc, it could
easily be because of a bug that has since been fixed.
Unfortunately, the gdc folks have never managed to release an
updated gdc that uses the D version of the compiler front-end,
so as I understand it, they're still stuck at 2.067 (which is
over 2 years old), whereas dmd is now at 2.072. ldc should be
reasonably up-to-date if you want an alternative to dmd, and I
expect that the gdc guys will get there eventually, but they
haven't yet.

- Jonathan M Davis

I just have compiled my example with ldc and everything is ok!
I was not aware of that concerning gdc. Thank you for this
information, I lost around 2 hours struggling with initial code
trying to guess what was wrong.
Conclusion: now I will only use ldc and dmd.
Thanks to Steven too for his clarification concerning
template<->symbol
Vincent
```
Nov 10 2016
Steven Schveighoffer <schveiguy yahoo.com> writes:
```On 11/10/16 12:12 PM, Jonathan M Davis via Digitalmars-d-learn wrote:
On Thursday, November 10, 2016 15:46:11 Picaud Vincent via Digitalmars-d-
learn wrote:
-------> What am I missing? What is the right way to do that?

Honestly, I'm surprised that the compiler let you alias
std.algorithm.comparison.min, because it's a templated function, and in the
case of templates, you alias instantiations of templates, not the templates
themselves.

This statement is not true at all. You alias symbols. Templates are symbols.

-Steve
```
Nov 10 2016
Jonathan M Davis via Digitalmars-d-learn writes:
```On Thursday, November 10, 2016 14:32:28 Steven Schveighoffer via
Digitalmars-d-learn wrote:
On 11/10/16 12:12 PM, Jonathan M Davis via Digitalmars-d-learn wrote:
On Thursday, November 10, 2016 15:46:11 Picaud Vincent via
Digitalmars-d-

learn wrote:
-------> What am I missing? What is the right way to do that?

Honestly, I'm surprised that the compiler let you alias
std.algorithm.comparison.min, because it's a templated function, and in
the case of templates, you alias instantiations of templates, not the
templates themselves.

This statement is not true at all. You alias symbols. Templates are
symbols.

Hmmm. I was sure that you couldn't, but I think that I was confusing myself
over issues having to do with partial template instantiation. So, I stand
corrected.

- Jonathan M Davis
```
Nov 10 2016