cross_module function overloading & alias & template: how to ?

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Nov 10 09:12:32 PST 2016


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
only reason that the compiler then distinguishes between your overload of
min and the one in std.algorithm is that yours is non-templated, and
non-templated function overloads take precedence over templated overloads.
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.

And if your goal is to simply mess around with D's overloading rules, you
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



More information about the Digitalmars-d-learn mailing list