C++ Primer第五版笔记——定义模板

函数模板:
类似两个数之间进行比较的功能,可能会发生在整数或小数上,可以通过定义一个通用的函数模板,而不用每个类型定义一个新函数。一个函数模板就是一个公式,可用来生成针对特定类型的版本:

template <typename T>
int compare(const T& v1,const T& v2 ){
    if(v1 > v2) return -1;
    if(v1 < v2) return 1;
    return 0    
}

模板定义以关键字template开始,后跟模板参数列表,这是一个以逗号分隔的一个或多个模板参数的列表。在模板定义中,模板参数列表不能为空。
模板参数列表很像函数的参数列表,函数参数列表指定若干特定类型的局部变量,但未指明如何初始化,在调用时以实参初始化;而模板参数列表连类型也未定义。
比如上面的compare函数声明一个名为T的类型参数,这个T表示一个类型,它的实际类型在编译时根据调用的实际情况来确定。

实例化函数模板:
当调用一个函数模板时,编译器(通常)用函数实参来为我们推断模板实参,例如实参类型是int时,编译器会推断出模板实参是int,并将其绑定到模板参数T。
编译器用这种方式来实例化一个特定版本的函数,也就是将T替换一下。

模板类型参数:
以上代码中的T就是一个模板类型参数,在类型模板参数前必须使用关键字class或template,这两个关键字的含义是相同的,可以互换使用,也可以同时使用。

非类型模板参数:
除了定义模板参数以外,还可以在模板中定义非类型模板参数。一个非类型模板参数表示一个值而不是一个类型,通过特定的类型名来指定非类型参数。
当一个模板被实例化时,非类型参数被一个用户提供的或编译器推断出的值所代替,这些值必须是常量表达式,从而允许编译器在编译时实例化模板。例如:

template <unsigned N,unsigned M>
int compare(const char (&p1)[N],const char (&p2)[M]){
    return strcmp(p1,p2);
}

当调用如下版本的compare时:

compare("hi","hello");

编译器会使用字面常量的大小来代替N和M,从而实例化模板,同时在字符串常量的末尾通常会添加一个空字符作为终结符。因此编译器实例化出的版本如下形式:

int compare(const char (&p1)[3],const char (&p1)[6]);

一个非类型参数可以是一个整型,也可以是一个指向对象或函数类型的左值引用。绑定到非类型参数的实参必定是一个常量表达式。
绑定到指针或引用非类型参数的实参必须有静态的生存期。
不能用一个普通(非static)的局部变量或动态对象作为指针或引用非类型模板参数的实参。
指针参数也可以用nullptr或一个值为0的常量表达式来实例化。

inline和constexpr的函数模板:
函数模板可以声明为inline和constexpr的:

template <typename T> inline T min(const T&,const T&);

编写类型无关的代码:
泛型编程的两个重要原则:
1.模板中的函数参数是const的引用
2.尽量降低函数对要处理的类型的要求。
通过将参数设置为const的引用,保证了函数可以作用于不能拷贝的类型;关于第二点,举个例子,在之前写的比较的那个函数,如果在编写代码时只是用”<”符号,就降低了函数对类型的要求,这个类型可以只支持<操作符,而不用支持>操作符。
模板程序应当尽量减少对实参类型的要求。

模板编译:
当编译器遇到一个模板定义的时候,它并不产生代码。只有当实例化出一个模板的一个特定的版本的时候才会产生代码,即在使用这个模板的时候编译器才会产生代码。
通常当调用一个函数或使用一个类类型的对象时,其函数的声明或类的定义是必须的,但是函数的定义或者类中成员函数的定义则不必已经出现,模板则不同:为生成一个实例化版本,编译器需掌握函数模板或类模板成员函数的定义,因此,与非模板代码不同,模板的头文件通常既包括声明也包括定义。

大多数编译错误在实例化期间报告:
模板在实例化时才产生代码这一特性影响了我们何时才能获知模板内代码的编译错误:
第一阶段:编译模板本身。在这个阶段,编译器通常不会发现很多错误,编译器可以检查语法错误;
第二阶段:编译器遇到模板使用时。在此阶段,编译器仍然没有什么可检查的,对于函数模板调用,编译器通常会检查实参数目是否正确,还能检查参数类型是否匹配,对于类模板,编译器可以检查用户是否提供了正确数目的模板实参。
第三阶段:模板实例化时。只有在这个阶段才能发现类型相关的错误。依赖于编译器如何管理实例化,这类错误可能在链接的时候才报告。
通常编译器会在第三阶段报告错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值