14.3.3 概念
模板有很多有用的特性,例如极大的灵活性和接近最优的性能,但不幸的是模板不是完美的。一如既往,优点伴随着缺点。主要问题是,获得高灵活性和性能的代价是模板的“内在”(定义)与其接口(声明)不能很好地分离。这令其错误诊断变得糟糕——通常只能得到相当糟糕的错误信息。有时,这些错误信息在编译过程中的出现时间远远落后于我们的期望。
当编译使用模板的代码时,编译器会“探查”模板内部以及模板实参。它这样做是为了获得生成优化代码所需的信息。为了获得这种信息,当今的编译器都要求在使用模板的地方必须能得到模板的完整定义。这包括调用的所有成员函数和所有模板函数。因此,模板的编写者会将模板定义放在头文件中。这并不是C++标准所要求的,但在有根本改进的C++编译器广泛普及之前,我建议你这样处理自己的模板:对于会在多个编译单元中使用的模板,将其定义放在一个头文件中。
这部分内容的学习应以编写简单模板开始,随后小心探索前进,获得更多经验。一种有用的技术是我们设计vector所采用的技术:首先设计一个针对特定类型的类并测试它。这个类设计好后,将特定类型替换为模板参数,并用不同的模板实参测试它。在实际编程中,应优先选用基于模板的库(如C++标准库)来获得通用性、类型安全和高性能。第15、16章介绍标准库容器和算法,会向你展示模板的使用。
C++14提供了一种机制,可极大地改善模板接口的检查。例如,我们如果在C++11中编写如下代码:
那么无法准确陈述对实参类型T有什么期望。C++标准描述了对实参类型有什么要求,但只是用英语描述的,而不是用编译器能理解的代码描述的。我们称一个模板实参应满足的要求集合为概念(concept)。一个模板实参必须满足模板对它的要求,即概念。例如,vector要求其元素能拷贝或移动、可获取地址且能默认构造(如果需要的话)。换句话说,元素必须满足一组要求——我们可以称之为Element。在C++14中,我们可以显式陈述概念: ...
