先考虑一个模板函数:
cpp
template<typename Seq, typename Value>
Value sum(Seq s, Value v)
{
for (const auto& x : s)
v+=x;
return v;
}
这个模板函数 sum 要求:
(1) 它的第一个模板参数是某种元素序列,并且
(2) 它的第二个模板参数是某种数,因为要进行加法运算。
更具体地讲,必须使用一对参数调用 sum :
一个序列 Seq,支持 begin() 和 end(),以便可以使用范围 for 进行遍历。
一种支持 += 运算符的算术类型 Value,以便可以对序列中的元素进行加法运算。
我们把这样的要求称为概念 (concepts)(即符合要求的表述对象 称为概念,这些表述对象可以转化为代码,可以用不同的代码实现)。
满足这种简化后的序列 (也称为范围) 要求以及更多要求)的类型示例包括标准库中的 vector、list 和 map。满足这种简化后的算术类型要求(以及更多要求)的类型示例包括 int、double 和 Matrix(对于任何合理的 Matrix 定义)。我们可以说 sum() 算法在两个维度上是通用的:用于存储元素的数据结构类型("序列")和元素的类型。
概念(concepts)不是任意的属性集合。 大多数类型(或一组类型)的属性列表都没有定义一个连贯且有用的概念。要使作为一个概念有用,需求列表必须反映一组算法或一组模板类操作的需求。在许多努力领域,人们已经设计或发现了描述该领域基本内涵(concept)的概念(concept) (C++ 中"concept"一词的技术用法就是考虑到这种常见用法而选择的)。 似乎很少有概念是有意义的(译注:大概指术语能反映事件的真实含义)。例如,代数建立在一元组(monad)、域(field) 和 环(ring) 等概念之上,而 STL 依赖于前向迭代器、双向迭代器和随机访问迭代器等概念。在一个领域找到一个新概念是一项重大成就;这不是你应该期望每年都做的事情。大多数情况下,你通过检查研究领域或应用领域的基础文本来找到概念。(注:此段表明概念是指事件的通用内涵。)
"concepts"是一个非常笼统的思想,在本质上与模板没有任何关系。 甚至 K&R C [Kernighan,1978] 也有概念,即有符号整数类型是编程语言对内存中整数概念的概括。我们对模板参数的要求也是概念(无论如何表达),因此与概念相关的大多数有趣问题都出现在模板的上下文中。(此段指的概念是指对模板参数施加的基本要求。)
**概念是精心设计的实体,反映了应用领域的基本属性。**因此,应该只有少数概念可以作为算法和类型设计的指导方针。这与物理插件 和插座类似;我们希望用最少的插头和插座简化我们的生活,并降低设计和建造成本。这种理想可能与每个单独的通用算法和每个单独的参数化类的最低要求理想相冲突。此外,这种理想可能与为类提供绝对最小接口的理想相冲突,甚至与一些程序员认为他们有权"完全按照自己喜欢的方式"编写代码相冲突。然而,如果不付出努力和某种形式的标准,我们就无法获得插件兼容性。
**也就是说,概念(符合要求的描述体)应当尽量反映通用性、一定的稳定性、跨多种算法的可用性、语义一致性等等,因此,概念不等于模板类或函数,但是模板类或函数是概念的一种很好的体现。**我们希望模板参数的许多简单约束都不符合概念的条件(指通用性的要求)。我们编写的许多模板并不反映通用算法或广泛适用的类型。相反,它们是实现细节,它们的参数只需反映模板的必要细节,该模板的目的在于在某事物的单一实现中一次性使用,对此类模板参数的要求为约束或(如果必须)临时概念(不具有通用性的模板参数称为约束或临时概念)。看待约束的一种方法是将它们视为接口的不完整(部分)规范。通常,部分规范很有用,而且比没有规范要好得多。