🥬重载与模板
2022-6-15
| 2023-8-2
0  |  阅读时长 0 分钟
type
status
date
slug
summary
tags
category
icon
password
Property
 
 
函数模板可以被别的模板或非模板函数重载。与往常一样,同名的函数必须在参数的数目或类型上有所差异。由于函数模板的出现导致的函数匹配的差异将表现在以下几个方面:
  • 一个调用的候选函数(candidate function)包括所有模板实参推断成功的函数模板实例;
  • 候选函数模板实例讲总是可行函数(viable function),这是由于模板实参推断会排除所有不可行的模板;
  • 与往常一样,可行函数事按照需要进行的转型进行排序的,对于函数模板来说这种转型是非常有限的;
  • 与往常一样,如果一个函数比其它函数提供了更优的匹配,此函数将被选中。然而,如果有好几个函数提供了一样好的匹配,那么:
    • 如果其中有一个非模板函数,那么这个非模板函数将被调用;
    • 如果没有非模板函数,但是多个函数模板中其中一个更加特化(specialized),那么这个更特化的函数模板将被调用;
    • 否则,调用是模糊的(ambiguous);
为了正确定义重载的函数模板需要对类型之间的关系以及模板函数的有限转型有一个良好的理解;
 

编写写重载模板

如下两个函数是重载的模板,如:
如果调用:string s("hi"); cout << debug_rep(s) << endl; 将只调用第一个函数 debug_rep 函数。如果以 cout << debug_rep(&s) << endl; 进行调用则两个模板函数都是可行的实例。第一个是 debug_rep(const string* &) 其中 T 被推断为 string*;第二个是 debug_rep(string*); 其 T 被推断为 string ;
然而第二个是精确匹配这个调用,第一个却需要将指针转为 const 的,函数匹配将更加青睐于第二个模板。
 

多个可行模板

考虑以下调用:
这里两个模板都是可行的而且是精确匹配的。第一个将被实例化为 debug_rep(const string* &),其 T 将绑定到 string*;第二个将被实例化为 debug_rep(const string*) 其 T 将绑定到 const string 上。此时常规的函数匹配将无法区别哪一个调用是更优的。然而,由于新加的关于模板的规则,将调用 debug_rep(T*) 函数,这个函数是更加特化的模板。原因在于,如果没有这个规则,将没有任何方法在这种情况下以 const 指针调用指针版本的 debug_rep。问题在于,debug_rep(const T&) 可以在任何类型上调用,包括指针类型。而 debug_rep(T*) 则只能在指针左值上调用,显然是更为特化的版本。
当多个重载版本的模板提供一样优秀的函数调用匹配,最特化的版本将胜出。
 

非模板和模板之间的重载

考虑非模板版本的 debug_rep 函数:
以及调用:
此时将有两个一样优秀的函数匹配:debug_rep<string>(const string&) 其 T 绑定到 string,以及这里定义的非模板函数。此时编译器将选择非模板版本。这是由于同样的原因,即最特化的将会被选择,非模板函数是比模板版本更加特化的。
需要注意的是在使用任何重载的函数时记得将这些函数(包括模板函数与非模板函数)在同一个头文件中进行声明。这样在进行函数匹配时编译器可以进行完全的考虑,而不至于忽略任何一个。
 
 
 
  • C++
  • 模板实参推断可变参数模板
    目录