template_1

0:
模板是一些为多种类型而编写的函数和类,而且这些类型都没有指定。当使用模板的时候,只需要把所希望的类型作为一个(显示或隐示的)实参传递给模板。模板是语言本身所具有的特效,她完全支持类型检查和作用域。

并不是把模板编译成一个可以处理任何类型的单一实体;而是对于实例化模板参数的每种类型,(编译器)都从模板产生出一个不同是实体。
这种用具体类型代替模板参数的过程叫实例化(instantiation)。她产生一个模板的实例。

1:
如何试图基于一个不支持模板内部所使用的操作的类型实例化一个模板,将会导致一个编译期错误。
so,模板被编译了两次:a,实例化之前,先检查模板代码本身语法是否正确;b,在实例化期间,检查是否所模板的有调用都有效。
这不同于普通函数中编译与链接之间的区别,对于普通函数只要有声明(不需要定义)就可以通过编译。然而当使用函数模板并引发模板实例化的时候,编译器需要查看模板的定义。

2:实参演绎deduction
template <typename T>//T是模板参数
inline T const& max (T const& a, T const& b)//a.b是调用参数
{
    return a < b ? b : a;
}
如果传递两个int给参数类型T const&,那么编译器能够得出结论:T必须是int。这里不允许进行自动类型转换。

max(4, 5.6);
error MSB6006: “CL.exe”
error C2782: “const T &max(const T &,const T &)”: 模板 参数“T”不明确
解决error:
对实参强制类型转换max(4, static_cast<int>4.2);
显示指定T类型指定两个不同类型参数。

inline T1 const& max (T1 const& a,  T2 const& b)
对于指定两个不同类型参数,由于该模板函数有返回类型,另个参数的实参可能要转型为返回类型而不会在意调用者意图;而且把另一个参数转型为返回类型的过程将会创建一个局部临时对象,所以返回类型必须是T1不能是T1 const& 。

因为调用参数(a,b)的类型构造自模板参数T,所有模板参数和调用参数通常是相关的。这个概念就叫实参演绎。
如max<double>(4, 4.2);用double实例化T,从而构造调用参数类型。

当模板参数和调用参数没有发生关联或不能由调用参数确定模板参数时,在调用时就必须显示指定模板实参。
template <typename T1, typename T2, typename RT>
inline RT max (T1 const& a,  T2 const& b);
模板实参演绎并不适合返回类型,因为RT不会出现在调用参数的类型里面,因此调用并不能演绎出RT。所以需要显示指导模板实参列表。
max<int, double, double> max(4, 4.2);

如果改变模板参数的声明顺序就只需指定返回类型
template < typename RT , typename T1, typename T2,>
max<double>(4, 4.2);
因为必须显示指定”最后一个不能被隐式演绎的模板之前的”所有实参类型,返回类型不能被演绎而调用参数可让演绎过程推导出。

3:重载函数模板
int const& max(int onst& a, int const& b)
{return a<b?b:a; }

template<typename T>
inline T const& max(T const& a, T const& b)
{return a<b?b:a; }

template<typename T>
inline T const& max(T const& a, T const& b, T const& c)
{ max(max(a, b), c); }

max(7,4,5);//调用三参数的模板
max(4.2, 3.0);//调用max<double>(通过实参演绎)
max(‘a’, ‘b’);//调用max<char>(通过实参演绎)
max(3, 5);//调用int重载的非模板函数
max(3, 5.1);//调用int重载的非模板函数
max<>(3, 5);// 调用max<int>(通过实参演绎)
max<double>(3, 5);// 调用max<double>(没实参演绎)

posted @ 2016-07-26 01:09  细雨细语  阅读(368)  评论(0编辑  收藏  举报