7.8 — Matching function calls to overloaded functions

Making a call to an overloaded function results in one of three possible outcomes:

  1. A best match is found. The call is resolved to a particular overloaded function.
  2. No match is found. The arguments can not be matched to any overloaded function.
  3. An ambiguous match is found. The arguments matched more than one overloaded function equally well.

When an overloaded function is called, the compiler goes through the following process to determine which version of the function will be called:

1) First, the compiler tries to find an exact match. This is the case where the actual arguments exactly match the parameter types of one of the overloaded functions. For example:

In this case, because 0 is an int, and there is a print(int) overload, an exact match is found. An exact match will always be considered the best match.

2) If no exact match is found, C++ tries to find a match through promotion. In a previous lesson (6.15 -- Implicit type conversion (coercion)), we covered how certain types can be automatically promoted to other types. To summarize,

  • Char, unsigned char, and short are promoted to int.
  • Unsigned short can be promoted to int or unsigned int, depending on the size of an int
  • Float is promoted to double
  • Enum is promoted to int

An int will not be promoted to an unsigned int (this is a conversion, not a promotion).

For example:

In this case, because an exact match print(char) could not be found, the char 'a' is promoted to an int, which then matches print(int).

3) If no promotion match is possible, C++ tries to find a match through standard conversion. Standard conversions include:

  • Any numeric type will match any other numeric type, including unsigned (e.g. int to unsigned int, int to float)
  • A 0 literal will match a pointer type or numeric type (e.g. 0 to char*, or 0 to float)
  • A pointer will match a void pointer

For example:

In this case, because there is no print(char) (exact match), and no print(int) (promotion match), the 'a' is converted to a double and matched with print(double).

Note that all standard conversions are considered equal. No standard conversion is considered better than any of the others.

4) Finally, C++ tries to find a match through user-defined conversion. Although we have not covered classes yet, classes can define conversions to other types that can be implicitly applied to objects of that class. For example, we might define a class X and a user-defined conversion to int.

Although x is of type class X, because this particular class has a user-defined conversion to int, the function call print(x) will resolve to the print(int) version of the function.

We will cover the details on how to do user-defined conversions of classes when we cover classes.

Ambiguous matches

If every overloaded function has to have unique parameters, how is it possible that a function call could result in more than one match? Because all standard conversions are considered equal, and all user-defined conversions are considered equal, if a function call matches multiple candidates via standard conversion or via user-defined conversion, an ambiguous match will result. For example:

In the case of print('a'), C++ can not find an exact match. It tries promoting 'a' to an int, but there is no print(int) either. Using a standard conversion, it can convert 'a' to both an unsigned int and a floating point value. Because all standard conversions are considered equal, this is an ambiguous match.

print(0) is similar. 0 is an int, and there is no print(int). It matches both overloads via standard conversion.

print(3.14159) might be a little surprising, as many programmers would assume it matches print(float). But remember that all literal floating point values are doubles unless they have the ‘f’ suffix. 3.14159 is a double, and there is no print(double). Consequently, it matches both calls equally well via standard conversion.

Resolving ambiguous matches

Ambiguous matches are considered a compile-time error. Consequently, an ambiguous match needs to be disambiguated before your program will compile. There are a few ways to resolve ambiguous matches:

1) Often, the best way is simply to define a new overloaded function that takes parameters of exactly the type you are trying to call the function with. Then C++ will be able to find an exact match for the function call.

2) Alternatively, explicitly cast the ambiguous argument(s) to the type of the function you want to call. For example, to have print(0) call print(unsigned int) in the above example, you would do this:

3) If your argument is a literal, you can use the literal suffix to ensure your literal is interpreted as the correct type:

The list of the most used suffixes can be found in lesson 4.13 -- Literals.

Matching for functions with multiple arguments

If there are multiple arguments, the compiler applies the matching rules to each argument in turn. The function chosen is the one for which each argument matches at least as well as all the other functions, with at least one argument matching better than all the other functions. In other words, the function chosen must provide a better match than all the other candidate functions for at least one parameter, and no worse for all of the other parameters.

In the case that such a function is found, it is clearly and unambiguously the best choice. If no such function can be found, the call will be considered ambiguous (or a non-match).

For example:

In the above program, all functions match the first argument exactly. However, the top function matches the second parameter via promotion, whereas the other functions require a conversion. Therefore, thus print(char, int) is unambiguously the best match.

%Missing lookup for lesson id 5480%

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">