刘未鹏 /文
C++的罗浮宫(http://blog.csdn.net/pongba)
Concepts无疑是C++0x的杀手级特性之一(或许称它“杀手级”还有一个原因:杀死新手:))。最近关于concepts的提案终于汇聚了Bjarne Stroustrup和Douglas Gregor领导的两派做法之长,已然有大局渐定的端倪。很多两派之间一直以来的分歧得到了漂亮的折衷;辅以concept_map这样漂亮而实用的特性,着实非常有说服力,而且,concept目前的实现居然隐含着一个潜在的decltype设施,前几天看到Douglas在boost.devel上提到,吓了一跳,自己怎么没有想到呢?想想也自然,人家可是ConceptGCC(GCC with Concepts support)的实现者这一,对于自己实现的东东,当然最熟悉了,呵呵。连David Abrahams看到这个trick时都说自己实在是dumb。Douglas给出的例子是推导函数/仿函数的返回值类型的,目前boost库里面的result_type设施的实现仍然是侵入式的,远不够完美。而有了concept之后,只需两三行代码即可实现一个完美的非侵入式result_type设施。实际上,concept作为aspect traits可以推导出一个类的任何成员签名里蕴含的类型来,当然也包括使其成为仿函数的operator()的返回值类型了。此外,就我的思考,concept可能蕴含着decltype的一个比较完善的非侵入式实现,至少比现在boost库里面的BOOST_TYPEOF用起来容易,后者需要注册类型,总的来说,concept引入了比目前的模板类型推导系统粒度更细的类型推导能力。
此外,concept的定义语法也逐渐成型成熟。虽然像late checking这样的特性我还是比较怀疑(实在有点“补丁”的感觉,目前这个特性也是整个concept系统里面最不稳定的,关于late_check的应用粒度问题还在揣摩当中,不过我想很可能这个特性会被剔除掉,而取代以更一般性的东西,毕竟显得太“孤立”了。)但毕竟来说整个concept系统已经呈现出所谓的“优雅”的感觉了,正如数学里面的“美”往往意味着正确一样,语言设计里的“优雅”也是如此。希望C++0x的这个主要特性能够漂亮的完成。本来打算单独介绍一下concept迄今为止走过的历史足迹的,然而重于还是抽不出时间好好组织一下,所以干脆只介绍一下最新进展了,有兴趣的朋友可以去C++ Committee Website上搜以往的proposal。
另一个我非常关心的template特性——variadic templates——最近也露出了十分可喜的迹象。Douglas终于在gcc上做出了第一份实现,并附带了一份新的提案和一个Introduction Paper,此外还用这个新特性重新实现了tuple、bind、function这三个已加入tr1的库,非常漂亮,光是代码量来说,tuple的我算了一下大概节省了2/3,此外还有大幅度提高的可读性和优雅性等等。这个新闻这阵子在新闻组上很是引起了一些兴奋~:) 跟以前的两份提案相比,新的提案暂时削减了几个小的特性,但主要的特性都已经实现了。这个快两年没有动静,然而十分优雅的语言特性总算迈出了一大步,说实话,前阵子看到C++议会语言进展列表里面把它排在“不活跃”一栏时真是有点担心呢,心想别又等到花都谢了菜都凉了。现在既然编译器实现已出,看来离成熟之期已然不远矣。热心如Alexandrescu者在comp.std.c++上对此也提出了不少建设性意见,看得出来不少人还是很看好这一特性的,尤其是boosters,光是它给模板库代码可读性带来的提高就是一大亮点,更何况还有代码量的大规模节省,一些十分诡异的(宏的、元编程的)技巧的废弃,等等,所有这些都会使得模板库代码朝向更优雅的方向发展。加上目前支持者甚众,估计进入0x是基本不会错的了。
并发内存模型是另一个杀手级特性,尽管是个默默无闻的杀手级特性。显然,这是所有新特性里面最难搞清楚的,因为多线程编程本来就是非常微妙的东西。Java前几年在这个上面花了相当多的工夫,呵呵,这次C++也就不打算重新发明轮子了,把现成的Java内存模型削减一些不附合C++国情的方面,“抄”过来即可:) 有兴趣的可以参考Java标准里面的内存模型部分,以及Boehm的主页上这方面的内容,Boehm是参加过Java内存模型的修订工作的,干起这方面来轻车熟路(http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/)。不过话说回来,刚才说过了这是个默默无闻的杀手级特性,说它杀手级是因为多线程从本质上无法完全以库的形式来实现,非得语言层面支持不可,而并发编程的时代已然到来,并发编程技术将会是极为重要的一项技术,一门现代的语言对此若没有健全的支持是无论如何不行的,所以这个特性对于C++的今后至关重要,其重要性甚至超过了concept/variadic template这些fancy的语法特性。而说它默默无闻则是因为它并不是需要程序员在日常编程中需要时时关心的东西,就像GC一样,它们都属于在背后默默无闻地提供支持和保障的特性。正如有了GC程序员就只需关心对象创建一样,有了并发内存模型的语言级支持,程序员就可以放心地将注意力放到真正的并发编程技术上面了。个人觉得C++在这个时候完善内存模型应该不算晚,甚至恰到好处,Herb Sutter说过并发编程的技术发展了这么多年到今天刚刚算是进入业界大规模应用的前夕,并发时代即将到来,而C++恰好将在未来三年内做好准备。对于像C++这样一门主要应用于大规模系统级应用/游戏/图形等开发中的语言,效率是非常重要的,而并发则是对效率的有力提升。
另外一个不得不说的“工业级”特性就是Module(模块),这也是一个对大规模C++应用能够带来显著好处的特性,相信熟悉的朋友都知道一个事实,现在C++应用尤其是大规模应用的系统编译构建速度越来越成问题,Intel内部的一个统计表明C++头文件中的代码量占整个项目代码量的比重从90年代的10%左右一直涨到现在的超过50%!而且还有上升趋势,因为以模板技术为基础的C++现代库将大量的代码放在头文件中,并且大量运用宏以及高级模板技术,使得编译构建时间大大增加。比如win32gui就是因为boost.signal带来的编译时间太巨而自己设计了一个轻量级的signal类(Qt用的也是自己的QSignal)。《Large Scale C++ Software Design》里面也说头文件的parse是项目构建里面很虚耗光阴的一个过程(并用多加一层“包含哨位”的笨重手法来缓解)。Module的出现,根据已有经验的预测,能够大幅度缓解这一问题。这也是其主要动因之一(Java是早就有了Module的)。此外Module还能带来另外一些好处(C++里面加入新特性就是这样,一般总要想尽办法挖掘新特性的潜在好处)。不过,像Module这样的工业级特性在新闻组上获得的喧哗反而远远不及一些漂亮的语法/类型系统层面的特性,希望不会在投票上落选吧:)
最后就是几个已经相当成熟的特性了,auto算是其一,实际上这么一个小巧实用,早该加入标准的东东从被提出那一天起就已经是铁板钉钉了。不过,跟auto算是孪生双胞胎的decltype倒是还在摇摆,我感觉decltype还没有定数主要还是它看上去太“难看”了,而且违反DRY原则,其提出的函数的新声明语法实在是有点别扭,倒是期望concept系统能够涵盖其能力,免得搞得太复杂。
当然,还有rvalue/move这个宠儿,rvalue/move也已经进入最终“订正“阶段了,所做的就是一些细微的调整,同样,这也是一个打一提出就等于是鱼上砧板的特性,用一句老美的话,It just feels right!(关于auto和rvalue/move,我以前的一篇做过一些介绍)
除此之外一些还比较有活力的特性有:Initializer(Bjarne领导,旨在统一初始化语法形式、以更好的支持C++的泛型系统。此外还提供更方便的初始化手段)、opaque typedef(比较有意思的特性,能够进一步强化C++的类型系统,减少某些因类型系统不够强健而带来的隐蔽错误的机会,Matthew在《Imperfect C++》中有一章就提到这个问题),跟opaque typedef有点关联的strong typed enums(这个不说大家也知道)、此外,还有aliasing template、new for-loop。
差不多吧,最主要的语言特性都在上面了。最令人遗憾的就是,看上去C++在0x是别指望能有reflection能力了。从新闻组上的反应来看,似乎committee guys和boosters对这一特性不是很热心,的确存在几个第三方的实现,不过都要借助于C++编译器之外的工具。看来很长一段时间内C++别指望有一个非侵入式的完美serialization库了。其它倒没太大关系,毕竟,C++的应用领域跟现在热火朝天的动态语言不同,后者非常依赖于类似reflection的能力。或许这也是那些guru们不关心这个的原因吧:)
写得匆忙,链接和文献就不一一列举了。主要来自C++ committee website(http://www.open-std.org/JTC1/SC22/WG21/)。