[转载]Bjarne Stroustrup关于C++新标准的文章[下面有中文翻译]//Tsubasa评:显然,C++ 9x拖到了C++0x接着拖到了C++ 1x

The C++ Source
A Brief Look at C++0x
by Bjarne Stroustrup
January 2, 2006

Summary
Bjarne offers a sneak peek at the next version of standard C++ ("C++0x") which should be complete by 2009.

The work on C++0x has entered a decisive phase. The ISO C++ committee aims for C++0x to become C++09. It follows that the standard must be complete for ratification by the ISO member nations in 2008. The set of facilities offered will be chosen from those currently being considered. To finish in time, the committee has stopped looking for new proposals and concentrates on the ones already being considered.

This paper briefly outlines the guiding principles of the work on C++0x, presents a few examples of likely language extensions, and lists some proposed new standard libraries.

[Note: This paper was first presented to the "Modern C++ Design & Programming" conference in Shanghai, November 18, 2005]

Guiding Principles
C++ is a general-purpose programming language with a bias towards systems programming that:

is a better C 
supports data abstraction 
supports object-oriented programming 
supports generic programming 
By "systems programming", I mean programming the kind of tasks traditionally associated with the operating system and fundamental tools. This includes the operating system kernel, device drivers, system utilities, networking, word processing tools, compilers, some kinds of graphics and GUI, database systems, games engines, CAD/CAM, telecommunications systems, etc. This kind of work is strongly represented among current C++ users. For example, see my "applications" page: http://www.research.att.com/~bs/applications.html.

The aim of C++0x is for that characterization above to remain true. It is not an aim to eliminate one of those styles (or "paradigms"; e.g. to make C++ less compatible with C) or to add a radically new paradigm. The most effective styles of programming use a combination of these techniques. Using these techniques in concert is often called "multi-paradigm programming," so we can say that we want to improve C++ as a multi-paradigm programming language.

The high level aims for the language part of C++0x are to:

Make C++ a better language for systems programming and library building

Rather than providing specialized facilities for a particular sub-community (e.g., numeric computation or Windows-style application development)

Make C++ easier to teach and learn

Through increased uniformity, stronger guarantees, and facilities supportive of novices

In other words, C++0x should be better than C++98 where C++98 is already strong—and maybe in a few more areas that are natural generalizations of what C++98 supports. When it comes to supporting specialized application areas, such as numeric computation, Windows-style application development, and embedded systems programming, C++0x will rely on libraries. The efficiency of the basic language features (such as, stack-allocated objects and pointers) plus the generality and flexibility of its abstraction mechanisms (such as classes and templates) make the use of libraries attractive in an incredibly broad set of application areas and reduce the need for new language features.

We cannot make the language simpler to teach and learn by removing features. Stability and compatibility are major concerns, so eliminating anything of importance (in any way) is not an option (and eliminating something of no importance would not be a help). This leaves us with the options of generalizing rules and adding easier-to-use features. We aim at both, but the latter is easier. For example, better library facilities, such as containers and algorithms, save users from some of the problems associated with lower-level facilities like arrays and pointers. Language facilities that simplify the definition and use of libraries (such as concepts and generalized initializer lists—see below) will therefore contribute to the ease of use of C++0x.

Some people object: "Don't dumb-down C++ for novices—there are languages enough for those", or "The sooner novices become experts the better!" These people have a point, but there will always be more novices than experts. Many C++ users quite reasonably don't want to become C++ experts—they are experts in their own fields (e.g., physicists, graphics specialists, or hardware engineers) who use C++. In my opinion, C++ has become too "expert friendly" and it will cost us little to provide much better support for "novices". It will cost us nothing in terms of performance (the zero-overhead principle still holds), in flexibility (we don't propose to prohibit anything), or in terseness of code. On the contrary, we aim to simplify expression of ideas. Finally, C++ is so large, is used in so many application areas, and there are so many useful C++ design techniques, that we are all "novices" much of the time.

The C++0x improvements should be done in such a way that the resulting language is easier to learn and use. Among the rules of thumb for the committee are:

Provide stability and compatibility (with C++98, and, if possible, with C)

Prefer standard library facilities to language extensions

Make only changes that change the way people think

Prefer generality to specialization

Support both experts and novices

Increase type safety (by providing safe alternatives to currently unsafe facilities)

Improve performance and ability to work directly with hardware

Fit into the real world

Naturally, applying these ideals and rules is an art rather than a science and people can (and do) disagree on what is a natural development of C++ and what would be a new paradigm. C++0x will most likely support optional garbage collection and it will support concurrency in the form of a machine model plus standard library facilities supporting threads (and maybe more). Some would consider that radical, but I don’t; people have used garbage collection with C++ for years (where that makes sense) and just about everybody uses threads sometime. In these cases, the issue is simply to standardize current practice.

We try to focus on extensions that "change the way people think" because that way we gain the greatest benefits for our efforts. Every change has a cost in terms of implementation, learning, etc., and the cost of a change does not always directly relate to its benefits. The major advances/benefits do not come from improving the way a programmer writes an individual line of code, but from improving the way a programmer solves problems and organizes programs. Object-oriented programming and generic programming have changed the way many people think—and that was the purpose of the C++ language facilities supporting those styles. Thus, the best use of our time as language and library designers is to work on facilities and techniques that help change the way people think.

Please note the last rule, "Fit into the real world". As usual for C++, the aim is not to create the most beautiful language—though we all prefer elegance when we can get it—but to provide the most useful language. This implies that compatibility, performance, ease of learning, and interoperability with other systems and languages are serious interrelated concerns.

Language Features
Let’s see how code using new C++0x features might look:

template<class T> using Vec = vector<T,My_alloc<T>>;Vec<double> v = { 2.3, 1.2, 6.7, 4.5 };sort(v);for(auto p = v.begin(); p!=v.end(); ++p)    cout << *p << endl;Each line except the last is illegal in C++98, and in C++98 we’d have to write more (error-prone) code to get the work done. I hope you can guess the meaning of this code without explanation, but let’s look each line individually.

template<class T> using Vec = vector<T,My_alloc<T>>;Here, we define Vec<T> to be an alias of vector<T,My_alloc<T>>. That is, we define a vector called Vec that works exactly like vector except that it uses my allocator (My_alloc) rather than the default allocator. The ability to define such aliases and to bind some but not all parameters of a template has been missing from C++. It has traditionally been referred to as a "template typedefs" because typedef is what we typically use for defining type aliases, but for technical reasons, we preferred using. One advantage of this syntax is that it introduces the name being defined where it is easy for the human reader to spot. Note also another detail. I didn’t write

template<class T> using Vec = vector< T,My_alloc<T> >;It will no longer be necessary to add that space between the terminating >'s. These two extensions have already been accepted in principle.

Next we define and initialize a Vec:

Vec<double> v = { 2.3, 1.2, 6.7, 4.5 };Initializing a user-defined container (vector<double,My_allocator<double>>) with an initializer list is new. In C++98, we can only use such initializer lists for aggregates (arrays and classic structs). Exactly how this extension will be achieved is still being discussed, but the solution will most likely involve a new kind of constructor—a "sequence constructor". Allowing the above implies that C++ better meets one of its fundamental design criteria: support user-defined and built-in types equally well. In C++98 arrays have a notational advantage over vectors. In C++0x, that will no longer be the case.

 

Next, we sort the vector:

sort(v); To do that within the framework of the STL we must overload sort for containers and for iterators. For example:

template<Container C> // sort container using <    void sort(C& c);      template<Container C, Predicate Cmp> // sort container using Cmp    where Can_call_with<Cmp,typename C::value_type>    void sort(C& c, Cmp less);      template<Random_access_iterator Ran> // sort sequence using <    void sort(Ran first, Ran last);      template<Random_access_iterator Ran, Predicate Cmp> // sort sequence using Cmp     where Can_call_with<Cmp,typename Ran::value_type>    void sort(Ran first, Ran last, Cmp less);This illustrates the most significant proposed C++0x language extension that is likely to be accepted: concepts. Basically, a concept is the type of a type; it specifies the properties required of a type. In this case, the concept Container is used to specify that the two first versions of sort need an argument that meets the standard library container requirements. The where-clauses are used to specify the required relationship between the template arguments: that the predicates can be applied to the containers' element types. Given concepts we can provide far better error messages than is currently possible and distinguish between templates taking the same number of arguments, such as

sort(v, Case_insensitive_less());   // container and predicateand

sort(v.begin(), v.end());           // two random access iteratorsThe difficulty in the design of “concept” is to maintain the flexibility of templates so that we don’t require template arguments to fit into class hierarchies or require all operations to be accessed through virtual functions (as for Java and C# generics). In “generics”, an argument must be of a class derived from an interface (the C++ equivalent to “interface” is “abstract class”) specified in the definition of the generic. That means that all generic argument types must fit into a hierarchy. That imposes unnecessary constraints on designs requires unreasonable foresight on the part of developers. For example, if you write a generic and I define a class, people can't use my class as an argument to your generic unless I knew about the interface you specified and had derived my class from it. That's rigid.

There are workarounds, of course, but they complicate code. Another problem is that you cannot use built-in types directly with generics, because built-in types, such as int, are not classes and don't have the functions required by interfaces specified by a generic—you then have to make wrapper classes for holding built-in types and access elements indirectly through pointers. Also, the typical operation on a generic is implemented as a virtual function call. That can be very expensive (compared to just using a simple built-in operation, such as + or <). Implemented that way, generics are simply syntactic sugar for abstract classes.

Given "concepts", templates will retain their flexibility and performance. There is still much work left before the committee can accept a specific and detailed concept design. However, concepts are a most likely extension because they promise significantly better type checking, much better error messages, and greater expressive power. That should lead to significantly better library interfaces, starting with the current standard containers, iterators, and algorithms.

Finally, consider the last line that outputs the elements of our vector:

for (auto p = v.begin(); p!=v.end(); ++p)    cout << *p << endl; The difference from C++98 here is that we don’t have to mention the type of the iterator: auto means “deduce the type of the declared variable from the initializer”. Such uses of auto are far less verbose and also less error-prone than current alternatives, such as:

for (vector< double, My_alloc<double> >::const_iterator p = v.begin(); p!=v.end(); ++p)    cout << *p << endl; The new language features mentioned here are all aimed at simplifying generic programming. The reason is that generic programming has become so popular that it is seriously strains the language facilities. Many “modern” generic programming techniques border on “write only” techniques and threaten to isolate its users. To make generic programming mainstream, as object-oriented programming was made mainstream, we must make template code easier to read, write, and use. Many current uses are too clever for their own good. Good code is simple (relative to what it is trying to do), easy to check, and easy to optimize (i.e., efficient). This implies that a wide range of simple ideas can be expressed simply in C++0x and that the resulting code is uncompromisingly efficient. The former is not the case in C++98—at least not for a sufficiently large range of techniques relying on templates. Better type checking and more extensive use of type information to shorten code will make code shorter and clearer, and easier to maintain, as well as more likely to be correct.

Library Facilities
Ideally, we’d leave the C++ language mostly unchanged and focus on adding standard libraries. However, libraries that are sufficiently general to be standard are not easy to design and the standards committee is—as usual—short of resources. We are a relatively small group of volunteers and all have “day jobs”. This puts unfortunate limits on how adventurous we can be with new libraries. On the other hand, the committee started early and a technical report on libraries ("The Library TR") was recently approved by vote. It provides several facilities that are directly useful to programmers:

Hash Tables 
Regular Expressions 
General Purpose Smart Pointers 
Extensible Random Number Facility 
Mathematical Special Functions 
I particularly appreciate having standard versions of regular expression matching and hash tables (called unordered_maps) available. In addition, the Library TR provides extensive facilities for builders of generic libraries building on the STL:

Polymorphic Function Object Wrapper 
Tuple Types 
Type Traits 
Enhanced Member Pointer Adaptor 
Reference Wrapper 
Uniform Method for Computing Function Object Return Types 
Enhanced Binder 
This is not the place to go into details about these libraries or into the further facilities that the committee would like to provide. If you are interested, I suggest you look at the proposals on the WG21 site (see “information sources” below), the libraries “wish list” (on my home pages), and the BOOST libraries (www.boost.org). I personally would like to see more libraries that are immediately useful to applications builders, such as Beman Dawes’ library for manipulating files and directories (currently a BOOST library) and a socket library.

The list of proposals is still quite modest and not anywhere as ambitious as I’d like. However, more proposals from the committee's large backlog of suggestions are being considered and more libraries will appear either as part of the C++0x standard itself or as further committee technical reports. Unfortunately, lack of resources (time, money, skills, people, etc.) will continue to limit progress in this direction. Sadly, I cannot offer hope for the most frequently wished for new standard library: a standard GUI library. A GUI library is simply too large a task for the volunteers of the C++ standards committee to handle and too difficult a task given the many (non-standard but huge, useful, and supported) GUI libraries available. Please notice that even though they are not standard, the major C++ GUIs have more users than most programming languages and are often better supported.

In addition to these general-purpose libraries, the committee presented a library interface to the most basic level of hardware in its “Performance TR”. That TR is primarily aimed to help embedded systems programmers and to disprove myths about poor performance of C++ code and about C++ being unsuitable for low-level tasks.

Putting It All Together
“Drawing all shapes in an array” is a classical example of object-oriented programming (going back to the early Simula days). Using generic programming, we can generalize that to drawing each element of any container holding (pointers to) shapes:

template<Container C>void draw_all(C& c)       where Usable_as<typename C::value_type,Shape*>{    for_each(c, mem_fun(&Shape::draw));}In C++0x, we hope to have Container as a standard concept and Usable_as as a standard predicate. The for_each algorithm is already in C++98, but the version that takes a container (rather than a pair of iterators) will have to wait for concepts in C++0x. The where-clause is a mechanism through which an algorithm can express requirements on its arguments. Here, draw_all() requires (obviously) that the elements of the container must be usable as (implicitly convertible to) Shape*. In this case, the where-clause gives us a degree of flexibility/generality not offered by simply requiring a container of Shape*'s. In addition to any container of Shape*'s, we can use any container with elements that can be used as Shape*'s, such as a list<shared_ptr<Shape*>> (where shared_ptr is a likely C++0x standard library class) or a container of pointers to a class derived from Shape*, such as deque<Circle*>.

Assuming that we have points p1, p2, and p3, we can test draw_all() like this

vector<Shape*> v = {    new Circle(p1,20),    new Triangle(p1,p2,p3),    new Rectangle(p3,30,20)}; draw_all(v); list<shared_ptr<Shape*>> v2 = {    new Circle(p1,20),    new Triangle(p1,p2,p3),    new Rectangle(p3,30,20)}; draw_all(v2);The "draw all shapes" example is important because when you can do that well, you can do much of what’s key to object-oriented programming. As written here, the example demonstrates the power of multi-paradigm programming by also employing generic programming (concepts and templates), conventional programming (e.g. the free-standing standard-library function mem_fun()), and simple data abstraction (the function object returned by mem_fun()). Thus, this simple example opens the door to a host of elegant and efficient programming techniques.

I hope that after looking a bit at this example, your reaction will be "How simple!" rather than "How clever! How advanced!" In my opinion, many people are trying too hard to be clever and advanced. The real aim of design and programming is to produce the simplest solution that does the job and express it in the clearest possible way. The aim of the C++0x design is to better support such simple solutions.

 

 

 

 

Information Sources
My web pages (http://www.research.att.com/~bs) contain much useful information. There you will find information about my own work (books, articles, interviews, FAQs, etc.) and links to sources that I find most helpful, such as a list of interesting C++ applications, a list of C++ compilers, and links to useful libraries (e.g., BOOST). In connection with C++0x, you can find:

"Wish lists" for language features and library facilities 
The Standard: IOC/IEC 14882—International Standard for Information Systems—Programming Language C++ 
The Performance TR: ISO/IEC PDTR 18015—Technical Report on C++ Performance. 
The Library TR: JTC1.22.19768 ISO/IEC TR 19768—C++ Library Extensions. 
A link to the WG21 (ISO C++ Standards Committee) site, where you can find all the proposals being considered 
A page with some of my proposals (including "concepts") to the committee. (Please remember that not all proposals are accepted and that essentially all proposals that are accepted incorporate major changes and improvements before acceptance.) 
Acknowledgements
Thanks to Rong Yao ("Royal") who encouraged me to clarify many points. Also thanks to Nicholas Stroustrup, Bjorn Karlsson, and students from my 689 class for their helpful comments.


About the Author
Bjarne Stroustrup is the designer and original implementor of the C++ Programming Language. He is currently the College of Engineering Endowed Chair in Computer Science at Texas A&M University. He formerly worked as the head of AT&T Lab's Large-scale Programming Research department, from its creation until late 2002.

 

翻译:

 

C++0x的工作已经进入了一个决定性的阶段。ISO C++委员会对C++0x的目标是使其成为“C++09”。这意味着我们要在2008年完成这个标准以便被ISO成员国批准。最后提交的标准设施将选自目前正被讨论的那些提案。为了按时完成此项工作,委员会已经停止审查新的提案并将精力集中于目前已经被讨论的那些提案上。
  
本文简要描述了C++0x标准化工作的指导原则,展示了一些可能的语言扩展的例子,并列出了一些被提议的新标准库设施。   
指导原则   
C++是一门偏向于系统编程的通用编程语言。它    
·是一个更好的C    
·支持数据抽象    
·支持面向对象编程    
·支持泛型编程   
当我说“系统编程”时,我是指传统上与操作系统以及基础工具有关的那一类编程任务。包括操作系统核心、设备驱动程序、系统工具、网络应用、字处理工具、编译器、某些图形和GUI应用、数据库系统、游戏引擎、CAD/CAM、电信系统,等等。这类工作在当前的C++用户中占有主导地位。例子参见我的个人主页“Applications”单元(http://www.research.att.com/~bs/applications.html)。   
C++0x的目标是使以上的说法仍然成立。它并不是要消除这些编程风格(styles)(或“paradigms”,范型)之一(比方说,使C++不那么兼容于C),或者添加一种全新的“范型”。最有效的编程风格是联合使用这些技术,这也就是我们常说的“多范型编程(multi-paradigm programming)”。因此,我们可以说我们希望改进C++使其成为一门更好的多范型编程语言。   

C++0x的高级目标是: 使C++成为一门更好的系统编程语言和构建库的语言。  
 - 而不是为特定子社群提供专用设施(例如数值计算或Windows风格的应用程序开发)。   
 -使C++更易于教和学。  
 - 通过增强的一致性、更强的保证以及针对新手的设施支持。   
换句话说,在C++98已经很强的领域(以及一些更多的、C++98支持的较为自然的、一般化的领域),C++0x应该比C++98做得更好。对于一些专有的应用程序领域来说,例如数值计算、Windows风格的应用程序开发、嵌入式系统编程,C++0x应该依赖于程序库。C++在基本语言特性(如基于栈的对象和指针)方面所具有的效率,和在抽象机制 (如类和模板) 方面所具有的通用性和灵活性,使得程序库在非常广泛的应用领域都能保持它的吸引力,也因此降低了C++对各种新的语言特性的需求。   
我们不能为了降低C++在教与学方面的难度,而去移除某些语言特性。保持C++稳定性与兼容性是我们主要的考虑。因此,不管是以什么方式来移除其中任何重要的特性都是行不通的(而移除其中不重要的特性对于解决问题又没有实质性的帮助)。那么留给我们的选择恐怕只有“将规则一般化”和“添加更易于使用的特性”。两者都是我们的目标,但是后者更容易一些。例如,更好的程序库(容器与算法)可以帮助用户避免一些底层设施(例如数组与指针)带来的问题。那些能够“简化程序库的定义和应用”的语言设施(例如“concepts”与“通用初始化器列表”,下面将会谈到它们)也将有助于改善C++0x的易用性。一些人可能对此持有反对意见,“不要为了新手而将C++降格,适合新手的语言已经有很多了!”,或者“最好的办法还是将新手变成专家!”这些人的观点并非毫无道理,但是现实是新手总比专家要多。而且许多C++用户完全不必、也没有意愿成为C++专家——他们是各自领域的专家(比如物理学家、图形学专家、硬件工程师),只不过他们需要使用C++。在我个人来看,C++已经太过“专家友好”了,我们完全可以在花费很少的情况下为“新手们”提供更好的支持。事实上,这种支持不会损及任何C++代码的性能(零成本原则依旧适用)、灵活性(我们不打算禁止任何东西)、与简洁度。相反,我们的目标是简化这些理念的表达。最后,值得指出的是,C++是如此之大,而且应用如此广泛,各种设计技巧可谓汗牛充栋,以至于我们很多时候也都是“新手”。 
  
C++0x的改进应该以这样的方式进行:结果所得语言应该更易于学和用。以下是委员会考虑的一些规则:   
·提供稳定性和兼容性(针对C++98而言,可能的话还有C)  
·优先考虑库设施,其次才是语言扩展   
·只进行可以改变人们思考方式的修改   
·优先考虑一般性而非专用性   
·同时为专家和新手提供支持   
·增强类型安全性(通过为当前不安全的设施提供安全的替代品)   
·改进直接处理硬件的性能和能力   
·适应现实世界   

当然,对这些思想和规则的应用与其说是一门科学不如说是一门艺术,人们对于什么才是C++的自然发展以及什么才是一种新的范型有着不同的意见。C++0x将极有可能支持可选的垃圾收集机制,并将以一个机器模型外加支持线程的标准库设施(可能还有别的)来支持并发编程。一些人也许认为这过于激进,但我并不这么认为:人们已经在C++中(在垃圾收集有意义的领域)使用垃圾收集很多年了,而且几乎每一个人都曾使用过线程。在这些情况下,我们需要做的不过是将现行的实践加以标准化而已。   我们之所以专注于“只进行可以改变人们思考方式的修改”,是因为这种方式可以使我们的努力获得最大的回报。每一项改变都有代价,不管是在实现方面、还是在学习等其他方面。而且,每项改变的代价并不总是直接和其带来的回报正相关。语言上的主要进步/收益并非体现在如何改进程序员编写的某一行代码上,而是体现在如何改进程序员解决问题和组织程序的方式上。面向对象程序设计和泛型程序设计改变了很多人的思考方式——这也是C++语言设施支持这些风格的目的。因此,作为语言和程序库的设计者来说,最好的做法就是把我们的时间投入到那些能够帮助人们改变思考方式的设施和技巧上。   

请注意最后一条规则“适应现实世界”。一如既往,C++的目标不是创建一门“最美丽”的语言(尽管只要有可能我们都希望“美丽”),而是提供最有用的语言。这就意味着兼容性、性能、易于学习,以及与其他系统和语言的互操作性,才是应该严肃考虑的问题。
  
语言特性  
 
让我们来看看使用C++0x新特性的代码的可能模样: 
template<class T> using Vec = vector<T,My_alloc<T>>;Vec<double> v = { 2.3, 1.2, 6.7, 4.5 };sort(v);for(auto p = v.begin(); p!=v.end(); ++p)    cout << *p << endl;  
在C++98中,除了最后一行代码外其余每一行都是不合法的,而且在C++98中我们不得不编写更多(易犯错误)的代码来完成工作。我希望无需我的解释你就可以猜测到这段代码的含义,不过我们还是逐行看一看。 template using Vec = vector>;   
在这里,我们定义Vec作为vector>的别名。换句话说,我们定义一个名为Vec的标准vector,其工作方式正如我们常用的vector那样,除了它使用我自己定义的配置器(My_alloc)而不是默认的配置器之外。C++中缺乏定义这种别名以及绑定(bind)部分而非全部模板参数的能力。按照传统,这被称为“template typedefs”,因为我们一般采用typedef来定义别名,但出于技术上的原因,我们偏向于使用using。这种语法的优势之一是,它将被定义的名字展示于易被人们发现的显著位置。还要注意另一个细节,我没有像下面这样写: template using Vec = vector< T,My_alloc >;   我们将不再需要在表示结束符的两个“>”之间添加空格。原则上这两个扩展已经被接受了。   
接下来我们定义和初始化一个Vec: Vec v = { 2.3, 1.2, 6.7, 4.5 };   采用一个初始化列表来初始化用户自定义容器(vector>)是一种新方式。在C++98中,我们只能将这种初始化列表语法用于聚合体(包括数组和传统的struct)。至于究竟如何实现这种语言扩展仍然在讨论中。最可能的解决方案是引入一种新型构造函数:“序列构造函数”。允许上面的例子可以运作将意味着C++更好地满足其基础设计准则之一:对用户自定义类型和内建类型的支持一样好。在C++98中,数组比vector具有记号上的优势。在C++0x中,情况将不再如此。   接下来,我们对该vector进行排序: sort(v);   为了在STL的框架内做这件事,我们必须针对容器和迭代器对sort进行重载。例如: // 使用 < 对容器排序 template void sort(C& c); // 使用 Cmp 对容器排序 template where Can_call_with void sort(C& c, Cmp less); // 使用 < 对序列排序 template void sort(Ran first, Ran last); // 使用 Cmp 对序列排序 template where Can_call_with void sort(Ran first, Ran last, Cmp less);   
template<Container C> // sort container using <    void sort(C& c);      template<Container C, Predicate Cmp> // sort container using Cmp    where Can_call_with<Cmp,typename C::value_type>    void sort(C& c, Cmp less);      template<Random_access_iterator Ran> // sort sequence using <    void sort(Ran first, Ran last);      template<Random_access_iterator Ran, Predicate Cmp> // sort sequence using 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,我们就可以提供比目前好得多的错误消息,并区分带有相同数目实参的模板,例如:
sort(v, Case_insensitive_less()); // 容器与判断式   
和 
sort(v.begin(), v.end()); // 两个随机访问迭代器   
在concepts的设计中存在的最大的困难是维持模板的灵活性,因此我们不要求模板实参适合于类层次结构或要求所有操作都能够通过虚函数进行访问(就象Java和C#的泛型所做的那样)。在这些语言的泛型中,实参的类型必须是派生自泛型定义中指定的接口(在C++中类似于接口的是抽象类)。这意味着所有的泛型实参都必须适合于某个类层次结构。这将要求部分开发人员在设计的时候就做一些不合理的预设,从而为他们强加一些不必要的约束。例如,如果你编写了一个泛型类,而我又定义了一个类,只有在我知道你指定的接口、并将我的类从该接口派生的情况下,人们才可以将我的类用作这个泛型类的实参。这种限制太过严格。   
当然对于这种问题总有解决办法,但那会使代码变得复杂化。另一个问题是我们不能直接在泛型中使用内建类型。因为内建类型(例如int)并不是类,也就没有泛型中指定接口所要求的函数——这时候你必须为这些内建类型做一个包装器类,然后通过指针来间接地访问它们。另外,在泛型上的典型操作会被实现为一个虚函数调用。那样的代价可能相当高(相对于仅仅使用简单的内建操作来说,比如+或者<)。以这种方式来实现的泛型,只不过是抽象类的“语法糖”。 
  
有了concepts之后,模板将保持它们的灵活性和性能。在委员会可以接受一个具体的concept设计之前,仍然有很多工作要做。然而,由于承诺显著更好的类型检查、更好的错误信息和更好的表达力,concepts将成为一个极有可能的扩展。它将使得我们从目前的标准容器、迭代器、和算法开始就能设计出更好的程序库接口。 
最后,考虑最后一行用于输出我们的vector元素的代码:
for (auto p = v.begin(); p!=v.end(); ++p) cout << *p << endl;  
 
这儿与C++98的区别在于我们不需要提及迭代器的类型:auto的含义是“从初始化器(initializer)中推导出所声明的变量的类型”。这种对auto的使用方式可以大大消除当前替代方式所导致的冗长和易出错的代码,
例如: 
for (vector< double, My_alloc >::const_iterator p = v.begin(); 
p!=v.end(); ++p) cout << *p << endl;   
这儿提到的新的语言特性的目标都在于简化泛型编程,原因在于泛型编程已经是如此流行,“使得现有语言设施受到了很大的压力”。许多“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++正变得不适合低层任务的流言蜚语。
  
总结   
“将一个数组中所有的形状绘制出来”是面向对象编程中一个经典的例子(回想早期Simula的日子)。使用泛型编程,我们可以将其泛化,从而支持绘制任意容器(存储着Shape指针)中的每个元素。 template void draw_all(C& c) where Usable_as { for_each(c, mem_fun(&Shape::draw)); }   在C++0x中,我们希望将Container作为一个标准concept,将Usealbe_as作为一个标准判断式。其中for_each算法已经在C++98中有了,但是接受容器(而非一对迭代器)作为参数的版本要依赖于C++0x中的concept。其中的where子句用于支持算法来表达其对于实参的要求。就这里来说,draw_all()函数(明确)要求容器中的元素必须可以被作为(即可以隐式转换为)Shape*使用。这里的where子句通过简单要求一个Shape*容器,为我们提供了某种程度的灵活性和通用性。除了元素为Shape*的任何容器外,我们还可以使用那些元素可以被用作Shape*的任何容器,例如list>(其中shared_ptr将有可能成为C++0x标准库中的一个类)、或者元素类型继承自Shape*的容器,例如deque。   假设我们有p1、p2、p3三个点,我们可以编写如下代码来测试draw_all(): vector v = { new Circle(p1,20), new Triangle(p1,p2,p3), new Rectangle(p3,30,20) }; draw_all(v); list> v2 = { new Circle(p1,20), new Triangle(p1,p2,p3), new Rectangle(p3,30,20) }; draw_all(v2);   “绘制所有形状”的例子很重要,因为如果你可以很好地实现它,那么你就掌握了大多数面向对象编程中关键的东西。通过融合泛型编程(concepts与模板)、常规编程(例如独立标准库函数mem_fun())、和简单数据抽象(mem_fun()函数返回的函数对象),上面的代码演示了多范型编程的力量。这个简单的示例为我们开启了一扇通往许多优雅和高效的编程技巧的大门。  
我希望在看完上面的例子之后,你的反应是“如此简单!”,而不是“如此聪明!如此高级!”在我看来,许多人都在聪明和高级的道路上太过投入。但设计与编程的真正目的是使用最简单的方案来完成工作,并用尽可能清晰的方式来表达。C++0x设计的目标便是更好地支持这样的简单方案。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/goldou/archive/2007/06/23/1663128.aspx

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值