16.7. Overloading and Function Templates16.7. 重载与函数模板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: 如果重载函数中既有普通函数又有函数模板,确定函数调用的步骤如下:
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. 重载集合包含三个函数:第一个模板处理简单值,第二个模板比较两个序列的元素,第三个是处理 C 风格字符串的普通函数。 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. 两个形参都是 int 类型。候选函数是第一个模板将 T 绑定到 int 的实例化,以及名为 compare 的普通函数。但该普通函数不可行——不能将 int 对象传给期待 char* 对象的形参。用 int 实例化的函数与该调用完全匹配,所以选择它。
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. 这个调用正如我们所期待的,调用普通函数。该函数和将 T 绑定到 const char* 的第一个模板都是可行的,也都完全匹配。根据规则 3b,会选择普通函数。从候选集合中去掉模板实例,只剩下普通函数可行。 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. 这个调用也绑定到普通函数。候选者是将 T 绑定到 char* 的函数模板的版本,以及接受 const char* 实参的普通函数,两个函数都需要稍加转换将数组 ch_arr1 和 ch_arr2 转换为指针。因为两个函数一样匹配,所以普通函数优先于模板版本。 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: 来看两个例子,看看为什么当重载集合中既有模板又有非模板版本的时候,设计正确工作的重载函数是困难的。首先,考虑用指针代替数组本身的 compare 调用: 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. 这个调用与模板版本匹配!通常,我们希望无论是传递数组,还是传递指向该数组元素的指针,都获得同一函数。但是,在这个例子中,将 char* 绑定到 T 的函数模板与该调用完全匹配。普通版本仍然需要从 char* 到 const char* 的转换,所以优先选择函数模板。 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: 另一个具有惊人结果的改变是,如果 compare 的模板版本有一个 T 类型的形参代替 T 的 const 引用,会发生的情况: 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*: 这个例子中,如果有一个普通类型的数组,则无论传递数组本身,还是传递指针,都将调用模板版本。调用非模板版本的唯一途径是在实参是 const char 或者 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. 在这些情况下,普通函数和函数模板都完全匹配。像通常一样,当匹配同样好时,非模板版本优先。
![]() |