Section 16.7. Overloading and Function Templates


16.7. Overloading and Function Templates

A function template can be overloaded: We can define multiple function templates with the same name but differing numbers or types of parameters. We also can define ordinary nontemplate functions with the same name as a function template.

Of course, declaring a set of overloaded function templates does not guarantee that they can be called successfully. Overloaded function templates may lead to ambiguities.

Function Matching and Function Templates

The steps used to resolve a call to an overloaded function in which there are both ordinary functions and function templates are as follows:

1.

Build the set of candidate functions for this function name, including:

  1. Any ordinary function with the same name as the called function.

  2. Any function-template instantiation for which template argument deduction finds template arguments that match the function arguments used in the call.

2.

Determine which, if any, of the ordinary functions are viable (Section 7.8.2, p. 269). Each template instance in the candidate set is viable, because template argument deduction ensures that the function could be called.

3.

Rank the viable functions by the kinds of conversions, if any, required to make the call, remembering that the conversions allowed to call an instance of a template function are limited.

  1. If only one function is selected, call this function.

  2. If the call is ambiguous, remove any function template instances from the set of viable functions.

4.

Rerank the viable functions excluding the function template instantiations.

  • If only one function is selected, call this function.

  • Otherwise, the call is ambiguous.

An Example of Function-Template Matching

Consider the following set of overloaded ordinary and function templates:

      // compares two objects      template <typename T> int compare(const T&, const T&);      // compares elements in two sequences      template <class U, class V> int compare(U, U, V);      // plain functions to handle C-style character strings      int compare(const char*, const char*); 

The overload set contains three functions: The first template handles simple values, the second template compares elements from two sequences, and the third is an ordinary function to handle C-style character strings.

Resolving Calls to Overloaded Function Templates

We could call these functions on a variety of types:

      // calls compare(const T&, const T&) with T bound to int      compare(1, 0);      // calls compare(U, U, V), with U and V bound to vector<int>::iterator      vector<int> ivec1(10), ivec2(20);      compare(ivec1.begin(), ivec1.end(), ivec2.begin());      int ia1[] = {0,1,2,3,4,5,6,7,8,9};      // calls compare(U, U, V) with U bound to int*      // and V bound to vector<int>::iterator      compare(ia1, ia1 + 10, ivec1.begin());      // calls the ordinary function taking const char* parameters      const char const_arr1[] = "world", const_arr2[] = "hi";      compare(const_arr1, const_arr2);      // calls the ordinary function taking const char* parameters      char ch_arr1[] = "world", ch_arr2[] = "hi";      compare(ch_arr1, ch_arr2); 

We'll look at each call in turn:

compare(1, 0): Both arguments have type int. The candidate functions are the first template instantiated with T bound to int and the ordinary function named compare. The ordinary function, however, isn't viablewe cannot pass an int to a parameter expecting a char*. The instantiated function using int is an exact match for the call, so it is selected.

      compare(ivec1.begin(), ivec1.end(), ivec2.begin()) 

compare(ia1, ia1 + 10, ivec1.begin()): In these calls, the only viable function is the instantiation of the template that has three parameters. Neither the template with two arguments nor the ordinary nonoverloaded function can match these calls.

compare(const_arr1, const_arr2): This call, as expected, calls the ordinary function. Both that function and the first template with T bound to const char* are viable. Both are also exact matches. By rule 3b, we know that the ordinary function is preferred. We eliminate the instance of the template from consideration, leaving just the ordinary function as viable.

compare(ch_arr1, ch_arr2): This call also is bound to the ordinary function. The candidates are the version of the function template with T bound to char* and the ordinary function that takes const char* arguments. Both functions require a trivial conversion to convert the arrays, ch_arr1 and ch_arr2, to pointers. Because both functions are equal matches, the plain function is preferred to the template version.

Conversions and Overloaded Function Templates

It can be difficult to design a set of overloaded functions in which some are templates and others are ordinary functions. Doing so requires deep understanding of the relationships among types and in particular of the implicit conversions that may or may not take place when templates are involved.

Let's look at two examples of why it is hard to design overloaded functions that work properly when there are both template and nontemplate versions in the overload set. First, consider a call to compare using pointers instead of the arrays themselves:

      char *p1 = ch_arr1, *p2 = ch_arr2;      compare(p1, p2); 

This call matches the template version! Ordinarily, we expect to get the same function whether we pass an array or a pointer to an element to that array. In this case, however, the function template is an exact match for the call, binding char* to T. The plain version still requires a conversion from char* to const char*, so the function template is preferred.

Another change that has surprising results is what happens if the template version of compare has a parameter of type T instead of a const reference to T:

      template <typename T> int compare2(T, T); 

In this case, if we have an array of plain char; then, whether we pass the array itself or a pointer, the template version is called. The only way to call the nontemplate version is when the arguments are arrays of const char or pointers to const char*:

      // calls compare(T, T) with T bound to char*      compare(ch_arr1, ch_arr2);      // calls compare(T, T) with T bound to char*      compare(p1, p2);      // calls the ordinary function taking const char*      parameters compare(const_arr1, const_arr2);      const char *cp1 = const_arr1, *cp2 = const_arr2;      // calls the ordinary function taking const char* parameters      compare(cp1, cp2); 

In these cases, the plain function and the function template are exact matches. As always, when the match is equally good, the nonoverloaded version is preferred.

It is hard to design overloaded function sets involving both function templates and nontemplate functions. Because of the likelihood of surprise to users of the functions, it is almost always better to define a function-template specialization (Section 16.6, p. 671) than to use a nontemplate version.



Exercises Section 16.7

Exercise 16.61:

Implement the three versions of compare. Include a print statement in each function that indicates which function is being called. Use these functions to check your answers to the remaining questions.

Exercise 16.62:

Given the compare functions and variables defined in this section, explain which function is called, and why, for each of these calls:

      compare(ch_arr1, const_arr1);      compare(ch_arr2, const_arr2);      compare(0, 0); 

Exercise 16.63:

For each of the following calls, list the candidate and viable functions. Indicate whether the call is valid and if so which function is called.

      template <class T> T calc(T, T);      double calc(double, double);      template <> char calc<char>(char, char);      int ival; double dval; float fd;      calc(0, ival);         calc(0.25, dval);      calc(0, fd);           calc (0, 'J');      } 




C++ Primer
C Primer Plus (5th Edition)
ISBN: 0672326965
EAN: 2147483647
Year: 2006
Pages: 223
Authors: Stephen Prata

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net