1. *** 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. However, overloaded function templates may lead to ambiguities. The steps used to resolve a call to an overloaded function in which there are both ordinary functions and function templates are as follows:
- Build the set of candidate functions for this function name, including:
a. Any ordinary function with the same name as the called function.
b. Any function-template instantiation for which template argument deduction finds template arguments that match the function arguments used in the call. - Determine which, if any, of the ordinary functions are viable. Each template instance in the candidate set is viable, because template argument deduction ensures that the function could be called.
- 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.
a. If only one function is selected, call this function.
b. If the call is ambiguous, remove any function template instances from the set of viable functions. - Rerank the viable functions excluding the function template instantiations.
a. If only one function is selected, call this function.
b. Otherwise, the call is ambiguous.
2. An Example of Function-Template Matching
template <typename T> int compare(const T&, const T&); |
再进行分析前,先看一个小例子:int compare(const char (&v1)[3], const char (&v2)[3]);
int compare(const char *v1, const char *v2);
int main(int argc, char **argv)
{
const char array1[] = "wo";
const char array2[] = "hi";
compare(array1, array2);
}
error: call of overloaded ‘compare(const char [3], const char [3])’ is ambiguous
note: candidates are: int compare(const char (&)[3], const char (&)[3])
note: int compare(const char*, const char*)
// 即编译器认为这个两个函数是同样好的。
compare(const_arr1, const_arr2):它的candidates只有int compare(const char*, const char*)
. 因为模板函数int compare(const T&, const T&)
中的参数类型是引用,const_arr1的类型是const char[6],const_arr2的类型是const char[3],两个实参的类型不同,所以不能使用模板进行实例化。
compare(const_arr1, const_arr1):它的candidates有int compare(const char*, const char*)
和int compare(const char (&)[6], const char (&)[6]
,由前面的例子可知,它们两个是一样好的,但是依据匹配规则,如果出现ambiguous的情况,则剔除由函数模板实例化而来的函数。
compare(ch_arr1, ch_arr2): 与compare(const_arr1, const_arr2)
类似。
3. Conversions and Overloaded Function Templates
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);
// 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 nontemplate 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 than to use a nontemplate version.