The library in the forthcoming C++ Standard (the Draft [I]) has evolved from nothing to a specification that takes over half the document. The library specification of over 340 pages was developed over the course of about 20 meetings of the C++ Standards committee. How was it possible to create so much in such a short time'? Only by making a large number of decisions on a large number of classes. This is a somewhat anecdotal history of how those decisions were reached.
In the beginning there was the ARM [2]. The ARM contains 16 chapters and a grammar summary. A quick comparison shows that the chapters from the ARM formed the basis of the first 16 chapters of the Draft. But there are 27 chapters (1) in the Draft. These additional 11 chapters represent the library. So while the core part of the language had a basis in the ARM, the library started with a blank sheet of paper. What were the original plans for the library? They were not very specific. There were three basic desires:
One of the first decisions the library group had to reach concerned the new operator. The new operator returned zero if no memory was available. This seemed like a perfect opportunity to use exceptions. However, that would, be changing existing practice. What should be done'? Many people thought that it would be a mistake to change the behavior of new. Throwing an exception would re quire existing code that tested for a return value of zero to change. But everyone was aware of existing code that did not perform the test. The result of the discussions was a decision to change new to throw an exception as the default and to provide a method to have it return zero when needed(3). This decision set a precedent for a number of future decisions by the committee. The library should not be afraid to incorporate the new features of the language. Indeed, it is often the first opportunity to try them.
This decision had other ramifications. The exception thrown by new needed definition. This naturally led to the standard exception classes. After defining one exception for new, it seemed that a general exception class should be defined. There was quite a bit of discussion over the form of this class, particularly whether or not it should use the string class. Since the library group had decided to not be afraid to use the new features of the language, some argued that strings should be used in the exception class. Unfortunately, a string might require the usage of dynamic memory, which could cause an exception to be thrown. A clever implementation might use a pre-allocated area for exceptions and avoid allocating memory, but it seemed better to use the simplest approach possible when handling exceptions. Therefore exceptions use a const char *.
Proposals for changes are submitted to the standards committee and go through what is essentially a political process on their way to acceptance. The definition of politics comes from the Greek words poli-, meaning "many", and -tics, meaning "small blood-sucking animals." As such, many people think it is a strange way to define a programming language. However, politics is also the art of accommodating the points of view of many different people and finding a way to reach consensus on a decision.
Two similar proposals were submitted to the commit tee at the same time by the same person, one for an auto_ptr class and one for a counted_ptr class. Even though the process was the same for both, one was accepted and the other was not. The first, auto_ptr, is a class which retains a pointer to dynamic memory that may be automatically deleted at the end of the block where it is defined. The second, counted_ptr, retains a pointer to dynamic memory and a count of the number of references to it. It deletes the memory when the count reaches zero. The first step for both of these proposals was examination by the library working group.
The committee splits into various working groups to consider proposals and to make recommendations for changes to the standard. Each group considers different aspects of the standard. The library working group is responsible for everything that affects the library. Proposals for changes to the library are first discussed in the library working group. The group has to decide if the proposals warrant consideration for inclusion in the standard. The main criteria are:
An item in the library should be generally useful in a large number of applications. Special purpose classes belong in special purpose libraries, not in the standard. Efficiency means that not only must the classes them selves have an efficient implementation, but there may he benefits to program efficiency in having them as part of the standard. In other words, a compiler that knows of their existence can implement them as special cases and greatly increase their efficiency. A simple or throw away class should not be added to the library. It can he written on an as-needed basis. Common understanding means they should be used in a fashion that people would expect. For example, we would not want to over load operator + to perform some obscure function. A new proposal should not change something that is currently in use in a surprising fashion, or contrary to existing practice. Also, the working group wanted to maintain some consistency across the library. A hunch of unrelated classes would work at cross purposes.
How did the auto_ptr and counted_ptr classes fare against these criteria. It was agreed that both classes were generally useful. Efficiency was not a major consideration for these proposals. There was a division of opinion over the complexity of these two classes. Some thought they were tricky enough to get right that they should be in the library, others thought that everyone could write their own. The problem with any small class is that everyone understands it, but everyone has a slightly different opinion about what it should do. Both these proposals had difficulties here, particularly counted_ptr. Everyone seemed to think it should work slightly differently than it did. There was no problem with existing practice. However, some thought that these classes were unrelated to the rest of the library.
After much discussion the library working group decided to approve both classes. After a working group approves a change, it goes before the committee as a whole for discussion, and, if the discussion is favorable, a formal vote. The whole committee shared many of the same concerns of those in the working group. Discussion in the committee did not reach a consensus on agreement. The committee usually does not move ahead with a proposal when it can not reach a consensus. Therefore neither proposal was accepted.
But, you may ask, why then is auto_ptr in the Draft? The answer lies partly in the make-up of the committee. It is combination of both the U.S. (ANSI) X3J16 group and the international (ISO) WG21 group. Al though the majority of members who attend the meeting are ANSI members, the final international standard will be approved only if a majority of individual countries vote for it. Each individual country has its own way of deciding how to vote. In the U.S., the Draft is published for public review. The comments received from public review are given to the X3J16 group for consideration. This group will form a recommendation to the overall U.S. standards body regarding acceptance of the Draft as a standard. The U.S. standards body uses the recommendation to help decide whether to accept or reject the Draft. Other countries act differently. Some form a small panel of experts to review the Draft and make comments. The answers from the committee to these comments, known as national body comments, decide how that country will vote. National body comments there fore get the most serious consideration by the committee.
It was these comments that gave an impetus to further consideration of auto_ptr. Some national bodies were concerned that there was no way to automatically release dynamic memory when an exception occurred. One way to solve this problem is to use auto_ptr. In the face of this serious concern, the committee decided to include auto_ptr in the library.
By far the largest class in the numerics part of the standard library is valarray. It is useful primarily to a small group of programmers concerned with mathematics. Why was this class included in a library of general purpose classes? Because it may be too inefficient to do valarray any other way. There are substantial benefits to scientific programming in C++. Overloading of functions and operators makes it possible to express equations in a straightforward fashion using C++. However, efficiency is of primary importance to large scale numeric operations. Such programs may execute for hours even on supercomputers. There can be a real benefit to having this class in the standard because compilers may provide optimal implementations of known classes.
But there are many classes that would be a real benefit to having in the standard. Why this one? Part of the answer lies in the committee process. The committee is a group of volunteers who spend their own and their company's time in helping to create the standard. It is impossible for a committee of volunteers to successfully create a complex class, propose it for the library, and respond to all comments. It is much more effective to make one person the focal point. Also, there just is not enough time to do intensive design work when you only meet three weeks a year. Almost all classes in the library are the result of a single, or small group, of individuals championing a proposal. A committee member interested in numeric programming proposed the valarray class. It was eventually accepted for the standard after discussions occurring over many meetings. Many times the committee is asked why a particular class is not in the library. The answer almost always is, "because nobody made a proposal."
The library grew slowly during the first few years of committee meetings. It contained several classes, a partial I/O streams definition, and the C library, by reference to the C Standard [3]. However, there was no list class and no map class. Few of the classes commonly available to C++ programmers were in the library because nobody had made a proposal for them. Then the Standard Template Library (STL) [4] was proposed for inclusion. This library was developed to support generic programming. It contained a large number of general purpose classes specifically de signed to provide an integrated framework for use. Be sides container classes like 1 i s t and map, it had iterator classes designed for accessing the containers, and algorithms for using them.
There were many issues involved regarding the inclusion of STL. One was the size. Adding STL would greatly increase the size of the library. It would end any idea of having a small library with only the most essential classes. Instead the standard library would become a more general purpose library.
The style of STL was also a consideration. STL pro motes a certain style of programming. It includes a great emphasis on templates. Conventional libraries used classes rather than templates. Adding STL would greatly increase the importance of templates in the language. Beyond that, the STL design imposes certain requirements on the library classes. STL expects containers to be us able by its algorithms and iterators. Every container must fulfill certain requirements to allow this. Everyone who designs his own container class would also have to meet these requirements to allow the STL algorithms to work.
There were many other considerations. For example, the STL algorithms contain requirements on complexity as a measure of efficiency. Should those requirements be in the standard'? Another consideration was copyrights and patents of the owners. Adding proprietary material to a standard could cause problems for compiler implementors and library vendors (4).
Two factors were the primary influence on the final decision to adopt STL. First, many people felt that the classes were extremely useful. Second, that the overall framework of STL was well designed and ties the entire library together.
Unfortunately, the classes that were already in the Draft were not designed with the STL framework in mind. Adding STL required an examination of classes that were already in the library. Many were adapted to use iterators and conform to the STL style. The bitstring class was dropped in favor of vector
< bool >.
The library working group accepted the task of providing a library usable throughout the world. When the string class was first designed it was with the plan that there would be a wstring class to handle wide characters. I/O streams would need to accept wide characters also. But wide characters in themselves are not sufficient to provide complete internationalization. Unfortunately, the members of the committee did not have a great deal of experience in this area. Both the U.S. and Europe have similar requirements on characters. It was not until the Japanese delegation began to take an active interest in C++ that large changes were made in this area.
Part of the changes added for internationalization came about during the evolution of the library to make widespread use of templates. The string class changed from being a character and wide character class to being a template that takes a character type as a parameter. This allows any character-type class to use strings. The stream classes were also converted to templates that were based on the character type. The result is a library that has many new features intended to support various types of characters and I/O.
Additional classes were added, in particular the locale and char traits classes. The locale class provides support for nationalization. This is much more extensive than what is currently in C. You can use several locales at a time based upon definitions of multiple locale objects. The char_traits class provides specific definitions and methods for each type of character. This is a specific use of a general idea. Having the characteristics of the parameterized class specialized separately makes it possible to write a generic template.
The library has met its original goals to a large extent. However, the library working group either changed or dropped some of those goals during the evolution of the library chapters. The goal to provide a minimal library was dropped in favor of providing increased functionality The effort to provide strings and I/O support went far beyond what anyone imagined at the beginning of this process. In part, that has reflected the changes to the core language itself. When the committee first began, few if any imagined the large number of changes and additions. The effect of these changes is reflected in the library. Originally, templates and exceptions were not in the library. Now exceptions are used and templates are the backbone of the entire library. It is amazing that after starting with so little, the standard library has grown into such an extensive, general-purpose library.
1 standards parlance they are called clauses. 2This goal is always stated as, "As close as possible to C but no closer." 3The original plan was to use the set_new_handler to provide the workaround to return zero. This was changed to provide new (nothrow) to prevent throwing the exception. The nothrow technique is easier to use and doesn't affect new on a global basis. 4Hewlett-Packard gave up all rights to STL to allow it to be included in the standard.
[I] KOENIG, A. Working Paperfor Draft Proposed
International Standard for Information Systems
Programming Language C++. Document Number:
X3J16/96-0178, WG21/N0996, 24 Sept. 1996.
[2] ELLIS, M.A., AND STROUSTRUP, B. TheAnnotated C++ Reference Manual. Addison-Wesley, Reading, Mass., 1990. [3] ISO/IEC ISO/IEC 9899:1990 Programming Languages - C and ISO/IEC:1990
Programming Languages - C Amendment 1. [4] STEPANOV, A., AND LEE, M. The Standard Template Library. Available from ftp://butler.hpl.ph.com/stl/stl.zip 31 0ct.1995.
David Dodgson (David.Dodgson@unisys.COMI) has been programming for Unisys since he received his M.S. degree from the University of Illinois 20 years ago. He has spent most of that time working on compilers. He has been a member of the C+ + Standards Committee and the Library Working Group since 1991.