Topic: Function Overloading


Author: ercs50@castle.ed.ac.uk (claire)
Date: 24 Sep 92 14:36:15 GMT
Raw View
I have some queries about the strictly better than rule relating to matching on
overloaded function calls.

Extract from ARM section 13.2 - (Extract 1)

"The best-matching function is the intersection of sets of functions that
best match on each argument.  Unless this intersection has exactly one
member, the call is illegal.  The function thus selected must be a strictly
better match for at least one argument than every other possible function
(but not necessarily the same argument for each function).  Otherwise, the
call is illegal."


QUERY 1.

I do not agree with the following example extracted from section 13.2

     struct A {};
     struct B : A{};
     struct C {};
     struct D : B, C {};

     void f(C*, C*);
     void f(A*, B*);

     D *pd;

     void g()
     {
        f(pd, pd);
     }

The ARM says
      set for 1st argument { (f(C*, C*)  f(A*, B*) }
      set for 2st argument { (f(C*, C*)  f(A*, B*) }

      The intersection has 2 members , so the call f(pd, pd) is ambiguous.

But I think
      set for 1st argument { (f(C*, C*) }
      set for 2st argument { (f(C*, C*)  f(A*, B*) }

      The intersection has only one member f(C*, C*) so we match on it.

My reasoning being that converting a D* to a C* is better than converting
a D* to a A*.  See the following extract from rule [3] of section 13.2 of
the ARM

[3] ... "Of these, if B is publicly derived directly or indirectly from A,
converting a B* to A* is better than converting to void* or const void *;
further, if C is publicly derived directly or indirectly from B converting a
C* to B* is better than converting to A* "

As a result of closely following the ARM our compiler reguards f(pd,pd) as
unambiguous.



QUERY 2

I have received the following example from a C++ user:-

---------------------- Start of User extract  ----------------------------

          double f(double, long);    /* f1 */
          double f(double, double);  /* f2 */
          long f(long, long);        /* f3 */

          main()
          {
              long l1, l2, l3;
              double d1, d2;
              l1 = f(l2, l3);  /* call 1 */
              d1 = f(d2, l1);  /* call 2 */
          }

          The compiler reports that call 2 is ambiguous, which I dispute.

          So, let's work through this example.

          Argument 1 is a double. The set of functions that match best on this
          argument is {f1, f2}.

          Argument 2 is a long. The set of functions that match best on this
          argument is {f1, f3}.

          The intersection of these sets is {f1}. This intersection has at
          least one member, and the call is therefore legal and
          unambiguous.  'f1' is a strictly better match on the first argument
          than 'f3' and on the second argument than 'f2'.


--------------------- End of User Extract ----------------------------------

I think the user's logic comes from the phrase "every other possible function"
- see Extract 1 at top of my mail message.  I on the other hand interpet it as

          f1 is not a strictly better than match on the first
          argument when compared to f2, and f1 is not a strictly better than
          match on the second argument when compared to f3.

My logic is based on the sets we have created for each argument .
            argument1 - {f1, f2}
            argument2 - {f1, f3}
and I use these sets as my bases for applying the strictly better than rule

I can support this by extracting the example out of the ARM section 13.2

----------------- Start of Extract --------------------------------

         struct A{}:
         struct B: A{};
         struct C{};
         struct D: B, C {};

         void f(C*, C*);     /* f1 */
         void f(B*, A*);     /* f2 */
         void f(A*, B*);     /* f3 */

         void gg()
         {
            f(pd, pd);   // still ambiguous
         }

"A conversion of a D* to a B* is better than the conversion of D* to A*, so
we get the best-match sets:

         set for 1st argument : { f1, f2}
         set for 2nd argument : { f1, f3}

The intersection has only one member f(C*, C*).  The match for f(C*, C*),
however, is not strictly better than the alternatives for any argument so the
call is ambiguous.  Without the rule requiring that a function must be strictly
better for at least one argument we would have been required to call f(C* C*).
That would have implied that by adding a function declaration the programmer
could resolve an ambiguity so that one of the original functions would have
been called.  That anomaly does not seem to be a desirable property"


----------------- End of Extract --------------------------------


This rule was added between version 2.0 and 2.1 of C++ as a strengthening of
the rules.  I did consider that the statement

     "The function thus selected must be a strictly better match for at least
      one argument than every other possible function (but not necessarily the
      same argument for each function)"

was in fact just clarification of the statement that had gone before and not
actually a new rule but this is not upheld by the following extract

    " Up to this point we have not used the rule that the best-matching
      function must provide not only a match that is better than or equal
      to the matches of all other functions for each argument, but also must
      provide a match that is strictly better for at least one argument"





This all gives rise to the following 3 questions

Question 1:  I don't understand the requirement of this rule.  Can anyone
             clarify it?

Question 2:  The example in the ARM which attempts to illustrate this rule is
             in fact (by my logic) wrong.  Do you agree with my logic or the
             ARM's?

Question 3:  Our users don't understand the rule either and C front compilers
             do not appear to implement it correctly. What is the correct
             interpretation?



I would be most grateful for any input on this issue
Could you please e-mail replies direct to me.

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
    * Name         :  Claire Jones                                  *
    * E-mail       :  claire@uk.ac.ed.epc   from JANET     or       *
    *              :  claire@epc.ed.ac.uk   from elsewhere          *
    * Phone        :  +44 31 225 6262                               *
    * Fax          :  +44 31 225 6644                               *
    * Organisation :  Edinburgh Portable Compilers Ltd              *
    * Address      :  17 Alva Street, Edinburgh, Scotland, EH2 4PH  *
    \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */