[Issue 1528] [tdpl] overloading template and non-template functions

d-bugmail at puremagic.com d-bugmail at puremagic.com
Sun Apr 7 07:33:14 PDT 2013


http://d.puremagic.com/issues/show_bug.cgi?id=1528



--- Comment #33 from Andrei Alexandrescu <andrei at erdani.com> 2013-04-07 07:33:07 PDT ---
Great thread. Sorry I'm late to it! Let me make an appeal to simplicity - even
if we come up with a very meaningful and consistent set of overloading rules,
we lose if they are complicated. Simplicity is very important for figuring out
what function will be called in a context.

In that spirit I'd like to propose a basic strategy as follows:

1. Define a SIMPLE partial ordering relation <= between functions called "at
least as specialized" (and correspondingly a strict version < meaning "more
specialized").

2. Whenever two or more functions match a call, there is a "winner" only if it
is more specialized than all other candidates. (Not all candidates must be
partially ordered among themselves, but the winner must be more specialized
than all others.) Otherwise, there is ambiguity.

Now for the simple partial ordering relation: consider a call to a function
fun(args) with two overloads fun1 and fun2 that would accept the arguments,
i.e. fun1(args) and fun2(args) would both compile in isolation.

To decide whether fun1 and fun2 are partially ordered, we look at the sets of
accepted arguments. If fun2 accepts any argument fun1 would accept, we write
fun1 <= fun2 and we say "fun1 is at least as specialized as fun2" or "fun2 is
not more specialized than fun1".

Now, if fun1 <= fun2 and fun2 <= fun1 then the two are "as specialized" so a
decision cannot be made between the two. If only one of the relations applies,
then one of them is strictly more specialized and it is preferred in an
overloaded call. If neither relation applies, the functions are unordered so
again a decision cannot be made.

On the examples given by Kenji:

    int f1(int a, double=10) { return 1; }
    int f1(int a, string="") { return 2; }

These functions are not ordered because e.g. f1(2, 3.4) would not be accepted
by the second overload and f1(2, "hello") would not be accepted. So the call
f1(5) is ambiguous.

    int f2(T:int)(T b, double=10) { return 1; }
    int f2(T:int)(T b, string="") { return 2; }

Same here, these overloads are not ordered.

    // vs deduced parameter
    int f3(int a) { return 1; }
    int f3(T)(T b) { return 2; }

Here the second overload accepts f3("hello") so the first overload is more
specialized. It will be preferred even in calls with an implicit conversion,
e.g. f3(cast(short) 42). THIS IS A DEPARTURE FROM C++'S RULES.

    // vs specialized parameter
    int f4(int a) { return 1; }
    int f4(T:int)(T b) { return 2; }

These two functions are in the same equivalence classes because they accept the
same argument sets: f4_1 <= f4_2 and f4_2 <= f4_1. So any call that would match
these two would be ambiguous. 

    // vs deduced parameter + template constraint (1)
    int f5(int a) { return 1; }
    int f5(T)(T b) if (is(T == int)) { return 2; }

The constraint is evaluated first and then "disappears" leaving two functions.
Of these, the non-template is more specialized.

    // vs deduced parameter + template constraint (2)
    int f6(int a) { return 1; }
    int f6(T)(T b) if (is(T : int)) { return 2; }

Same here. Given that the constraints are arbitrary Boolean expressions, we
can't make good estimates on what sets of arguments they'll match.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------


More information about the Digitalmars-d-bugs mailing list