为了在STL的框架内做这件事,我们必须针对容器和迭代器对sort进行重载。例如:
// 使用 < 对容器排序
template<Container C>
void sort(C& c);
// 使用 Cmp 对容器排序
template<Container C, Predicate Cmp>
where Can_call_with<Cmp,typename C::value_type>
void sort(C& c, Cmp less);
// 使用 < 对序列排序
template<Random_access_iterator Ran>
void sort(Ran first, Ran last);
// 使用 Cmp 对序列排序
template<Random_access_iterator Ran, Predicate Cmp>
where Can_call_with<Cmp,typename Ran::value_type>
void sort(Ran first, Ran last, Cmp less);
这里演示了C++0x目前提议中最具意义的扩展部分(也是有可能被接受的部分):concepts。基本上,一个concept就是一个type的type,它指定了一个type所要求的属性。在这个例子中,concept Container用于指定前两个版本的sort需要一个满足标准库容器要求的实参,where子句用于指定模板实参之间所要求的关系:即判断式(predicate)可以被应用在容器的元素类型上。有了concepts,我们就可以提供比目前好得多的错误消息,并区分带有相同数目实参的模板。
在concepts的设计中存在的最大的困难是维持模板的灵活性,因此我们不要求模板实参适合于类层次结构或要求所有操作都能够通过虚函数进行访问(就象Java和C#的泛型所做的那样)。在这些语言的泛型中,实参的类型必须是派生自泛型定义中指定的接口(在C++中类似于接口的是抽象类)。这意味着所有的泛型实参都必须适合于某个类层次结构。这将要求部分开发人员在设计的时候就做一些不合理的预设,从而为他们强加一些不必要的约束。例如,如果你编写了一个泛型类,而我又定义了一个类,只有在我知道你指定的接口、并将我的类从该接口派生的情况下,人们才可以将我的类用作这个泛型类的实参。这种限制太过严格。
当然对于这种问题总有解决办法,但那会使代码变得复杂化。另一个问题是我们不能直接在泛型中使用内建类型。因为内建类型(例如int)并不是类,也就没有泛型中指定接口所要求的函数——这时候你必须为这些内建类型做一个包装器类,然后通过指针来间接地访问它们。另外,在泛型上的典型操作会被实现为一个虚函数调用。那样的代价可能相当高(相对于仅仅使用简单的内建操作来说,比如+或者<)。以这种方式来实现的泛型,只不过是抽象类的“语法糖”。
有了concepts之后,模板将保持它们的灵活性和性能。在委员会可以接受一个具体的concept设计之前,仍然有很多工作要做。然而,由于承诺显著更好的类型检查、更好的错误信息和更好的表达力,concepts将成为一个极有可能的扩展。它将使得我们从目前的标准容器、迭代器、和算法开始就能设计出更好的程序库接口。
这儿与C++98的区别在于我们不需要提及迭代器的类型:auto的含义是“从初始化器(initializer)中推导出所声明的变量的类型”。这种对auto的使用方式可以大大消除当前替代方式所导致的冗长和易出错的代码。
这儿提到的新的语言特性的目标都在于简化泛型编程,原因在于泛型编程已经是如此流行,“使得现有语言设施受到了很大的压力”。许多“modern”的泛型编程技术接近于“write only”技术,并有孤立于其用户的危险。为了使得泛型编程成为主流(就象面向对象编程成为主流那样),我们必须使模板代码更易于阅读、编写、和使用。许多目前的用法只管编写时候的好处。但真正好的代码应该简洁(相对于它要做的事情来说)、易于检查、和易于优化(也就是高效)。这就意味着许多简单的思想可以在C++0x中简单地进行表达,并且结果代码坚定不移得高效。在C++98中前者的情况可不是这样,至少对于非常大范围的依赖于模板的技术的情况不是如此。借助于更好的类型检查和类型信息更广泛的使用,C++代码将会变得更简短、清晰、易于维护,也更容易获得正确性。
库设施
从理想上说,我们应该尽量不修改C++语言,而集中于扩充标准库。然而,那些具有足够大的通用性的能够进入标准的库设计起来并不容易,而且一如既往,标准委员会缺乏足够的资源。我们由相对少的一组志愿者构成,并且都有“日常工作”。这就给我们能对新库进行的冒险添加了不幸的限制。另一方面,委员会很早就开始库的工作了,一个关于库的技术报告(Library TR)也在最近被投票通过了,它提供了一些对程序员来说具有直接的用处的设施:
·哈希表(Hash Tables)
·正则表达式(Regular Expressions)
·通用智能指针(General Purpose Smart Pointers)
·可扩展的随机数字设施(Extensible Random Number Facility)
·数学专用函数(Mathematical Special Functions)
我尤其赏识能够有标准版本的正则表达式和哈希表(名为unordered_map)。此外,Library TR还为基于STL构建泛型库的人们提供了广泛的设施:
·多态函数对象包装器(Polymorphic Function Object Wrapper)
·Tuple类型
·Type Traits
·增强的成员指针适配器(Enhanced Member Pointer Adaptor)
·引用包装器(Reference Wrapper)
·用于计算函数对象返回类型的统一方法(Uniform Method for Computing Function Object Return Types)
·增强的绑定器(Enhanced Binder)
这儿不是详述这些库的细节或者深入讨论委员会希望提供的更多的设施的场合。如果你对此感兴趣,我建议你看看WG21站点(参见后面的“信息资源”)上的提案、库“期望列表(wish list)”(在我的主页上),以及BOOST库(http://www.boost.org/)。我个人希望看到更多的对应用程序构建者有着直接好处的库,例如Beman Dawes的用于操纵文件和目录的库(当前是一个BOOST库)以及一个socket库。
目前的提案列表仍然相当的保守,并不是各个地方都如我所期望的那样进取。不过,还有更多来自于委员会海量的建议中的提案正被考虑,将有更多的库或者成为C++0x标准的一部分、或者成为将来委员会的技术报告。不幸的是,资源的缺乏(时间、财力、技能、人力等)仍将继续限制我们在这个方向上的进展。悲哀的是,我无法给大家太希望得到的一个新标准库——一个标准GUI库——带来希望。GUI库对于C++标准委员会的志愿者来说是一个太大的任务,而且是一个太困难的任务,因为已经有很多(非标准、大型、有用、但受支持的)GUI库的存在。请注意,纵然它们是非标准的,主要的C++ GUI库还是有比大多数编程语言更多的用户,并且通常有更好的支持。
除了这些通用的库之外,委员会还在“Performance TR”中提呈了一个到最基层的硬件的库接口。该TR的首要目标是帮助嵌入式系统程序员,同时还驳斥了有关C++代码性能低下以及C++正变得不适合低层任务的流言蜚语。