对于实例化模板参数的每种类型,都要从模板中产生一个不同的实体
模板被编译了两次,分别发生在:
1.实例化之前,先检查模板代码本身,查看语法是否正确;在这里会发现错误的语法,如遗漏分号等。
2.在实例化期间,检查模板代码,查看是否所有的调用都有效。在这里会发现无效的调用,如该实例化类型不支持某些函数调用等。
模板参数:
例1:
template <typename T1, typename T2>
inline T1 max (T1 const& a, T2 const& b) {
return a < b ? b : a;
}
...
max(4, 4.2);
在上例中,有2个缺点:
1.必须声明返回类型。
2.把第2个参数转型为返回类型的过程将会创建一个新的局部临时对象,这导致了不能通过引用来返回结果,即返回类型必须是T1,而不能是T1 const&。
初步解决办法为:显示指定模板实参列表
将例1修改如下:
template <typename RT, typename T1, typename T2>
inline RT max (T1 const& a, T2 const& b) {
return a < b ? b : a;
}
...
max<double>(4, 4.2);
这样,调用max<double>时,显示地把RT指定为double,而另两个参数T1和T2可以根据调用实参分别演绎为int和double。
重载函数模板:
重载解析过程通常会调用更为匹配的非模板函数,而不会从该模板产生出一个实例。
例2:
- #include <cstring>
- #include <string>
- // maximum of two values of any type (call-by-reference)
- template <typename T>
- inline T const& max (T const& a, T const& b)
- {
- return a < b ? b : a;
- }
- // maximum of two C-strings (call-by-value)
- inline char const* max (char const* a, char const* b)
- {
- return std::strcmp(a,b) < 0 ? b : a;
- }
- // maximum of three values of any type (call-by-reference)
- template <typename T>
- inline T const& max (T const& a, T const& b, T const& c)
- {
- return max (max(a,b), c); // error, if max(a,b) uses call-by-value
- }
- int main ()
- {
- ::max(7, 42, 68); // OK
- const char* s1 = "frederic";
- const char* s2 = "anica";
- const char* s3 = "lucas";
- ::max(s1, s2, s3); // ERROR
- }
错误原因:
对于C-string而言,这里的max(a,b)产生了一个新的临时局部值,该值有可能会被外面的max函数以引用的方式返回,而这将导致传回无效的引用。
小结:
- 当你传递模板实参的时候,可以根据实参的类型来对函数模板进行实例化。
- 可以显示指定模板参数。
- 可以重载函数模板。
- 当重载函数模板的时候,把你的改变限制在:改变参数的数目和显示地指定模板参数。
- 一定要让函数模板的所有重载版本的声明都位于它们被调用的位置之前。