Previous | Table of Contents | Next |
6.5.5.4. Template Instantiation
Unfortunately, the ARM was not sufficiently specific about how a definition of a template function was to be presented to a compilation system. My intent was to maintain the usual C and C++ model of compilation where a function can be called given only a declaration specifying its calling interface as long as its definition is supplied in some compilation unit. This is sometimes called the separation model of template compilation. The first (Cfront-based) implementation of templates provided that. However, separate compilation of template functions is hard, and it was possible to misread the ARM text so as not to require it. Furthermore, to encourage experimentation with alternative implementation strategies, the ARM specifically allowed implementors to impose constraints on the way template definitions were presented to the compilation system. The first PC implementation of templates, provided in Borlands Release 4.0, simply required the definition of a template function to be in scope wherever the template was called.
Requiring a programmer to supply the definition of a template everywhere it is used (called the inclusion model of template compilation) simplified the compilation process so much that John Spicer of the C++ compiler company Edison Design Group started a long campaign to make this model the only one required by the standard. I considered the option of including a template definition with every use acceptable and in the spirit of the way a programmer can request inlining for a function. However, I considered a requirement to include a template definition with every use unacceptable because this forces a programmer to merge the source text of unrelated modules into a single compilation. Such merging can cause surprising changes of meaning by changing the context of a definition. In particular, there is no effective way of protecting a definition from having its meaning changed by unexpected macros. For a long time, these two views proved irreconcilable and the standards committee basically separated into two opposing camps over the template compilation model issue. Neither camp had the massive majority necessary to settle the issue in a way that satisfied the ANSI and ISO requirement for a consensus.
Fortunately, the stalemate was broken by a clever and innovative proposal from a group of people from SGI, including Matt Austern, Jim Denert, and John Wilcox. That proposal focused on the ways that names in a template definition were resolved. The idea was to formulate those rules in such a way that the meaning of a use of a template would in most cases be independent of how a programmer presented it to the compilation system. The technique simplifies separate compilation of template functions to the point where a function can be generated from a template at link time from partially compiled source code. This implies that generation of new functions from a template at runtime is possible for systems with runtime linking. In addition, the technique provides a degree of protection against interference between code from different logical modules included in a single compilation unit.
The fundamental idea is to bind a name used within a template definition at the definition point unless the name depends on a template argument. If a name depends on a template argument, it is looked up in scopes related to its actual template parameters in a way that minimizes dependence of the location of the use and the location of the template definition. If different name bindings can result from lookups at different points of use of a template given the same template arguments, such uses of the template are illegal (Stroustrup, 1997).
Exceptions were considered in the original design of C++ but were postponed because there wasnt time to do a thorough job of exploring the design and implementation issues. Exceptions were considered essential for error handling in programs composed out of separately designed libraries.
The actual design of the C++ exception mechanism stretched from 1984 to 1989. Andrew Koenig was closely involved in the later iterations and is the coauthor (with me) of the published papers (Koenig & Stroustrup, 1989a, 1990). I also had meetings at Apple, DEC, Microsoft, IBM, Sun, and other places where I presented draft versions of the design and received valuable input. In particular, I searched out people with actual experience with systems providing exception handling to compensate for my personal inexperience in that area. Throughout the design effort, there was an increasing influence of systems designers of all sorts and a decrease of input from the language design community. In retrospect, the greatest influence on the C++ exception-handling design was the work on fault-tolerant systems started at the University of Newcastle in England by Brian Randell and his colleagues, and continued in many places since.
The following assumptions were made for the design:
These assumptions, together with the requirement that C++ with exceptions should cooperate smoothly with languages without exceptions, such as C and Fortran, led to a design with multilevel propagation. The view is that not every function should be a firewall and that the best error-handling strategies are those in which only designated major interfaces are concerned with non-local error-handling issues. By allowing multilevel propagation of exceptions, C++ loses one aspect of static checking. One cannot simply look at a function to determine which exceptions it may throw. C++ compensates by providing a mechanism for specifying a list of exceptions that a function may throw.
Previous | Table of Contents | Next |