6.6.1. Argument Type Conversions

Image

In order to determine the best match, the compiler ranks the conversions that could be used to convert each argument to the type of its corresponding parameter. Conversions are ranked as follows:

1. An exact match. An exact match happens when:

• The argument and parameter types are identical.

• The argument is converted from an array or function type to the corresponding pointer type. (§ 6.7 (p. 247) covers function pointers.)

• A top-level const is added to or discarded from the argument.

2. Match through a const conversion (§ 4.11.2, p. 162).

3. Match through a promotion (§ 4.11.1, p. 160).

4. Match through an arithmetic (§ 4.11.1, p. 159) or pointer conversion (§ 4.11.2, p. 161).

5. Match through a class-type conversion. (§ 14.9 (p. 579) covers these conversions.)

Matches Requiring Promotion or Arithmetic Conversion
Image

Image Warning

Promotions and conversions among the built-in types can yield surprising results in the context of function matching. Fortunately, well-designed systems rarely include functions with parameters as closely related as those in the following examples.


In order to analyze a call, it is important to remember that the small integral types always promote to int or to a larger integral type. Given two functions, one of which takes an int and the other a short, the short version will be called only on values of type short. Even though the smaller integral values might appear to be a closer match, those values are promoted to int, whereas calling the short version would require a conversion:

void ff(int);
void ff(short);
ff('a'),   // char promotes to int; calls f(int)

All the arithmetic conversions are treated as equivalent to each other. The conversion from int to unsigned int, for example, does not take precedence over the conversion from int to double. As a concrete example, consider

void manip(long);
void manip(float);
manip(3.14); // error: ambiguous call

The literal 3.14 is a double. That type can be converted to either long or float. Because there are two possible arithmetic conversions, the call is ambiguous.

Function Matching and const Arguments

When we call an overloaded function that differs on whether a reference or pointer parameter refers or points to const, the compiler uses the constness of the argument to decide which function to call:

Record lookup(Account&);       // function that takes a reference to Account
Record lookup(const Account&); // new function that takes a const reference
const Account a;
Account b;
lookup(a);   // calls lookup(const Account&)
lookup(b);   // calls lookup(Account&)

In the first call, we pass the const object a. We cannot bind a plain reference to a const object. In this case the only viable function is the version that takes a reference to const. Moreover, that call is an exact match to the argument a.

In the second call, we pass the nonconst object b. For this call, both functions are viable. We can use b to initialize a reference to either const or nonconst type. However, initializing a reference to const from a nonconst object requires a conversion. The version that takes a nonconst parameter is an exact match for b. Hence, the nonconst version is preferred.

Pointer parameters work in a similar way. If two functions differ only as to whether a pointer parameter points to const or nonconst, the compiler can distinguish which function to call based on the constness of the argument: If the argument is a pointer to const, the call will match the function that takes a const*; otherwise, if the argument is a pointer to nonconst, the function taking a plain pointer is called.


Exercises Section 6.6.1

Exercise 6.52: Given the following declarations,

void manip(int, int);
double dobj;

what is the rank (§ 6.6.1, p. 245) of each conversion in the following calls?

(a) manip('a', 'z'),

(b) manip(55.4, dobj);

Exercise 6.53: Explain the effect of the second declaration in each one of the following sets of declarations. Indicate which, if any, are illegal.

(a) int calc(int&, int&);

int calc(const int&, const int&);

(b) int calc(char*, char*);

int calc(const char*, const char*);

(c) int calc(char*, char*);

int calc(char* const, char* const);


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset