home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / prog / c / cpp.lha / paper.mss < prev    next >
Text File  |  1991-04-15  |  33KB  |  692 lines

  1. .nr PS 10
  2. .nr VS 12
  3. .nr PD .7v
  4. .nr LL 6.5i
  5. .TL
  6. A Portable Implementation of Parameterized Templates
  7. Using A Sophisticated C++ Macro Facility
  8. .AU
  9. Mary Fontana
  10. LaMott Oren
  11. .AI
  12. Texas Instruments Incorporated
  13. Computer Science Center
  14. Dallas, Texas, 75265
  15. .AU
  16. Martin Neath
  17. .AI
  18. Texas Instruments Incorporated
  19. Information Technology Group
  20. Austin, Texas, 78759
  21. .AB
  22. The Texas Instruments C++ Object-Oriented Library (COOL) is a collection of
  23. classes, templates and macros for use by C++ programmers writing complex
  24. applications.  Parameterized types, symbolic computing and exception handling
  25. are significant features of COOL which improve the development capabilities
  26. available to the programmer.  These features are implemented in COOL with a
  27. sophisticated C++ macro facility.  This paper describes the COOL macro
  28. facility, discusses how support for parameterized templates is built upon it,
  29. and provides details of two programmer interfaces (both implemented) for easy
  30. use of parameterized templates in application programs.
  31. .AE
  32. .NH 1
  33. Introduction
  34. .LP
  35. The Texas Instruments C++ Object-Oriented Library (COOL) is a
  36. system-independent software platform consisting of classes, templates and
  37. macros for use by C++ programmers writing complex applications. It is designed
  38. to raise the level of abstraction for the programmer in order to facilitate
  39. concentration on the problem domain, not on implementing basic data structures,
  40. macros, and classes.  Parameterized templates, symbolic computing, and
  41. exception handling are significant features of COOL that substantially improve
  42. the development capabilities available.  We wished to provide these facilities
  43. in a compiler- and machine-independent manner across several hardware
  44. platforms.  We examined the macro language found in standard C-preprocessors
  45. and determined that it was insufficient for implementing these features.  As a
  46. result, we developed the COOL macro facility to allow the programmer to define
  47. powerful extensions to the C++ language in a seamless and unobtrusive manner.
  48. This macro facility is implemented as an extension to a C preprocessor [1].
  49. The modifications made to the preprocessor are both portable and compiler
  50. independent.  This paper describes this enhanced macro facility, discusses how
  51. parameterized templates is built upon it, and provides details of two
  52. programmer interfaces (both implemented) for easy use of parameterized
  53. templates.  For an overview of COOL see the paper,
  54. .I
  55. COOL - A C++ Object-Oriented Library 
  56. .R
  57. [2].
  58. For complete details, see the reference document,
  59. .I
  60. COOL User's Manual
  61. .R
  62. [3].
  63. .FS
  64. The authors may be reached via electronic mail at fontana@csc.ti.com,
  65. oren@csc.ti.com, and neath@itg.ti.com.
  66. .FE
  67. .NH 1
  68. The COOL Preprocessor and the defmacro Keyword
  69. .LP
  70. Many C++ language implementations separate the preprocessor and compiler
  71. functions into two separate programs. Others combine the preprocessor and
  72. compiler into one step. Since we needed a portable utility to massage C++
  73. source code that works under both scenarios and executes after include files
  74. and standard preprocessor directives have been expanded, but before the C++
  75. compiler itself begins parsing, we decided to modify a C-preprocessor to
  76. support the COOL C++ language extensions. Thus, the COOL preprocessor is
  77. derived from and based upon a public domain C-preprocessor (the DECUS C
  78. preprocessor) made available by the DEC User's group and supplied on the X11R3
  79. source tape from MIT. It has been modified to comply with the draft ANSI C
  80. specification with the exception that trigraph sequences are not supported.
  81.  
  82. The draft-proposed ANSI C standard indicates that extensions and changes to the
  83. language or features implemented in a preprocessor or compiler should be made
  84. by using the \fB#pragma\fR keyword.  The COOL preprocessor recognizes a
  85. \fB#pragma defmacro\fR declaration and is the single hook through which
  86. features such as the class macro, parameterized templates, and polymorphic
  87. enhancements have been implemented. The \fBdefmacro\fR keyword provides a way
  88. to define and execute arbitrary filter programs or macro expanders on C++ code
  89. fragments.  The syntax of the \fBdefmacro\fR declaration is:
  90. .DS I
  91. \fB#pragma \fBdefmacro \fIname \fB"\fIprogram\fB"\fI options\fR
  92. \fB#pragma \fBdefmacro \fIname \fB<\fIprogram\fB>\fI options\fR
  93. .DE
  94. where \fIname\fR is the name of the macro, \fIprogram\fR is either the name of
  95. an executable file or the name of an internal preprocessor function which
  96. implements the macro expansion, and \fIoptions\fR are any combination of the
  97. following optional parameters:
  98. .DS I
  99. \fBrecursive\fR        - the macro may be recursively expanded.
  100. \fBexpanding\fR        - the input to the macro is expanded.
  101. \fBdelimiter= \fIx\fR    - the default delimiter (semi-colon) is replaced with \fIx\fR.
  102. .DE
  103. Unknown \fIoptions\fR are passed as arguments to the macro expander named
  104. \fIprogram\fR.  This provides the necessary handle through which COOL functions
  105. and language extensions can be identified. For example, the \fBMACRO\fR
  106. and \fBtemplate\fR keywords are defined in a top-level header file with:
  107. .DS I
  108. #pragma defmacro MACRO "macro" delimiter=} recursive
  109. #pragma defmacro template "template" delimiter=}
  110. .DE
  111. The implementation of the macro expander program may be either external or
  112. internal to the preprocessor.  Fundamental COOL macro-expanders are implemented
  113. internal to the COOL preprocessor for the sole reason of providing a more
  114. efficient execution profile to reduce compile time for the application
  115. programmer.  When the preprocessor encounters a \fBdefmacro\fR declaration in
  116. the source code, it searches first for an executable file named \fIprogram\fR
  117. on the same search path as that used for include files.  If a match is not
  118. found, it then searches for \fIprogram\fR in an internal preprocessor function
  119. table.  If a match is still not found, an error is reported indicating that the
  120. macro expander could not be found.  This search order allows an internal
  121. preprocessor definition to be overridden by an external one.
  122.  
  123. When a \fBdefmacro\fR name is successfully recognized, the name and all
  124. following characters upto and including the delimiter character (including all
  125. matching and nested levels of \fB{} [] () <> "" ''\fR and comments found along
  126. the way) are piped into the standard input of the macro expander program.  The
  127. expander program performs whatever function(s) is appropriate and the resulting
  128. massaged character stream is piped back onto the standard output of the macro
  129. expander.  This output stream is scanned as new input by the preprocessor for
  130. any further processing that might be necessary. The original text in the source
  131. file is replaced with the preprocessor output before being sent onto the C++
  132. compiler.  The expansion replacing a \fBdefmacro\fR name in the source code is
  133. C++ 2.0 syntax acceptable to any conforming C++ translator or compiler [4].
  134. .NH 1
  135. The MACRO Keyword
  136. .LP
  137. The COOL \fBMACRO\fR keyword provides a powerful and flexible macro
  138. capability used to implement and simplify many of the features and functions
  139. contained in the library. A \fBdefmacro\fR named \fBMACRO\fR (all uppercase)
  140. provides an enhanced \fB#define\fR macro that supports multi-line, arbitrary
  141. length, nested macros and cpp-directives with positional, optional, optional
  142. keyword, required keyword, rest, and body arguments. \fBMACRO\fR has the
  143. following syntax:
  144. .DS I
  145. \fBMACRO \fIname\fR \fB( \fIparmlist\fR\fB ) { \fIbody\fR \fB}\fR
  146. \fIparmlist\fR  :=  [\fBKEY:\fR | \fBREST:\fR | \fBBODY:\fR] \fIidentifier\fR [\fB=\fR \fIidentifier\fR] [\fB,\fR \fIparmlist\fR]
  147. .DE
  148. where \fIname\fR is the name of the macro, \fIparmlist\fR is a list of
  149. parameters separated by commas, and \fIbody\fR is the code which replaces the
  150. \fBMACRO\fR reference. The \fIparmlist\fR specification allows positional,
  151. keyword, rest, and body parameters to be identified by the programmer.  The
  152. positional and keyword parameters may be required or optional. Optional
  153. parameters are supported by use of an equal sign followed by an
  154. \fIidentifier\fR that specifies the default value.  All the optional
  155. positional parameters must follow all of the required positional ones.  
  156.  
  157. When \fBKEY:\fR is specified in the \fIparmlist\fR, all parameters which follow
  158. are keyword parameters.  Keyword parameters are position-independent
  159. parameters.  A keyword parameter is provided a value in an argument list by
  160. supplying the keyword name followed by an equal sign and the argument value.
  161. \fBREST:\fR in the \fIparmlist\fR indicates that the remaining parameters are
  162. referenced by one named \fIidentifier\fR.  An optional equal sign followed by
  163. an \fIidentifier\fR sets the \fIidentifier\fR after the equal sign to the
  164. number of arguments remaining.  Finally, \fBBODY:\fR in the \fIparmlist\fR
  165. indicates that the parameter which follows is expanded to include all the
  166. source code within the braces after the \fBMACRO\fR call.  This is useful for
  167. passing a source code fragment onto other nested \fBMACRO\fRs. Examples of these
  168. three types of arguments are given below.
  169. .NH 2
  170. MACRO Examples
  171. .LP
  172. The following examples show some of the power and flexibility of \fBMACRO\fR.
  173. This first example uses both positional parameters and keyword parameters.
  174. .DS I
  175. MACRO set_val (size, value=NULL, KEY: low=0, high) {
  176.     init (size, value, low, (high-low))
  177. }
  178. .DE
  179. \fBset_val\fR has three parameters: \fIsize\fR is a required positional
  180. parameter, \fIvalue\fR is an optional positional parameter that if not
  181. specified in a particular call has a default value of \fBNULL\fR, \fIlow\fR is
  182. an optional keyword parameter with a default value of \fB0\fR, and \fIhigh\fR is
  183. a required keyword parameter.  In this example, the expansion calls the
  184. function \fBinit\fR with four arguments. The following shows several expansions
  185. of \fBset_val\fR.
  186. .DS I
  187. set_val (0, high=20)        ---->       init (0, NULL, 0, (20-0))
  188. set_val (0, low=5, high=15)    ---->       init (0, NULL, 5, (15-5))
  189. set_val (1, 2, high=25)        ---->       init (1, 2, 0, (25-0))
  190. .DE
  191. The next example uses the \fBREST:\fR parameter.  Note that there are two
  192. \fBMACRO\fRs defined: \fBbuild_table\fR calls \fBbuild_table_internal\fR
  193. to do most of the work.
  194. .DS I
  195. MACRO build_table (name, REST: rest) {
  196.     char* name[] = { build_table_internal(rest) NULL}
  197. }
  198.  
  199. MACRO build_table_internal (first, REST: rest=count) {
  200.     #first,
  201.     #if count
  202.     build_table_internal (rest)
  203.     #endif
  204. }
  205. .DE
  206. \fBbuild_table\fR has two parameters: \fIname\fR is the name of the table of
  207. \fBchar*\fR's and \fIrest\fR refers to all the remaining arguments.
  208. \fBbuild_table\fR calls \fBbuild_table_internal\fR passing its \fIrest\fR
  209. argument.  Note that this call is embedded within the initialization braces of
  210. the table and is followed by a \fBNULL\fR. In \fBbuild_table_internal\fR,
  211. \fIfirst\fR is set to the first argument of the \fIrest\fR argument list in the
  212. invoking macro call, and the remaining \fIcount\fR arguments are left in
  213. \fIrest\fR. \fBbuild_table_internal\fR uses the ANSI \fB#\fR character on
  214. \fIfirst\fR to double quote the value. A conditional clause tests \fIcount\fR
  215. to see if there are remaining arguments.  If \fIcount\fR is non-zero, the macro
  216. is called recursively with the remaining arguments.  When there are no more
  217. arguments, \fBbuild_table\fR regains control and appends the \fBNULL\fR
  218. character and closing brace to the result of \fBbuild_table_internal\fR.
  219.  
  220. A sample use of \fBbuild_table\fR is shown below to illustrate the construction
  221. of a \fBNULL\fR-terminated table containing character strings.  The first line
  222. shows the macro call and the second shows the resulting expansion.
  223. .DS I
  224. build_table (table, 1,2,3,4,5,6,7); 
  225. .DE
  226. expands to: 
  227. .DS I
  228. char* table[] = {"1", "2", "3", "4", "5", "6", "7", NULL};
  229. .DE
  230. This last example uses the \fBBODY:\fR parameter and also takes advantage of
  231. the current position feature found in the COOL container classes [2]. This is
  232. used to implement a general purpose loop macro similar to that found in Common
  233. LISP [5].
  234. .DS I
  235. MACRO LOOP (type, identifier, object, BODY: body) {
  236.     { type identifier;
  237.       for ( object.reset(); object.next(); ) {
  238.         identifier = object.value();
  239.         body
  240.       }
  241.     }
  242. }
  243. .DE
  244. \fBLOOP\fR has four parameters: \fItype\fR is the type of each element in a
  245. container class (such as, \fBint\fR), \fIidentifier\fR is the name of a
  246. variable to be declared of the given type, \fIobject\fR is the name of a
  247. container class instance, and \fIbody\fR is the body of code to apply on each
  248. element in the container object.  A specific example for the parameterized
  249. \fBList<int>\fR class is shown below.
  250. .DS I
  251. extern List<int> list1;
  252. LOOP (int, var1, list1) { cout << var1; }
  253. .DE
  254. expands to:
  255. .DS I
  256. extern List<int> list1;
  257. { int var1;
  258.   for ( list1.reset(); list1.next(); )  {
  259.     var1 = list1.value();
  260.     cout << var1;
  261.   }
  262. }
  263. .DE
  264. In this example, \fBlist1\fR is an instance of \fBList<int>\fR which is a
  265. container class representing a list of integers.  \fBLOOP\fR takes this list
  266. object and iterates through the elements, assigning each to a temporary integer
  267. variable \fBvar1\fR and printing its value.  The net result will print all
  268. elements in the list.
  269. .NH 1
  270. COOL Parameterized Templates
  271. .LP
  272. One of the main uses of the COOL macro facility is the implementation
  273. of \fBtemplate\fR, \fBDECLARE\fR and \fBIMPLEMENT\fR for supporting
  274. parameterized templates.  The syntax of the \fBtemplate\fR grammar is that as
  275. specified by Stroustrup in his paper,
  276. .I
  277. Parameterized Types for C++ 
  278. .R
  279. [6].  
  280. COOL fully implements this functionality such that there will be minimal source
  281. code conversion necessary when this feature is finally implemented in the C++
  282. language.  COOL provides templates for a number of parameterized classes (such
  283. as, \fBRange\fR and \fBIterator\fR) and container classes (such as,
  284. \fBVector\fR, \fB List\fR, \fBBinary_Tree\fR and \fBHash_Table\fR) which are
  285. described in
  286. .I
  287. COOL User's Guide 
  288. .R
  289. [3].
  290. .NH 2
  291. The template Keyword
  292. .LP
  293. The \fBtemplate\fR keyword provides a mechanism for defining parameterized
  294. classes.  A parameterized class is a type-independent class.  A typical use is
  295. a container class where the type of the contained object is specified at
  296. compile-time.  For example, vectors can be declared to hold a specific type
  297. of element, such as, a vector of integers or a vector of doubles,
  298. from a single parameterized class, \fBVector<\fItype\fB>\fR.
  299.  
  300. A \fBtemplate\fR is divided into the declarative part and the implementation
  301. part of a class.  The declarative part may occur many times in an application
  302. and is analogous to including a header file for a class which contains the
  303. class definition and its inline member functions.  The implementation part is
  304. analogous to the file that contains the source code implementing the member and
  305. friend functions of the class.  COOL provides four variations of \fBtemplate\fR
  306. for these two parts:
  307.  
  308. .DS I
  309. \fBtemplate\fR <\fBclass\fR \fItype\fR [, \fIparms\fR]> \fBclass\fR \fIname\fR<\fItype\fR> { \fIclass_description\fR };
  310. .RS
  311. Defines the class template for the declarative part of the \fIname\fR class.
  312. .RE
  313.  
  314. \fBtemplate\fR <\fBclass\fR \fItype\fR [, \fIparms\fR]> \fBinline\fR \fIresult name\fR<\fItype\fR>::\fIfunction\fR { ... };
  315. .RS
  316. Defines an inline member function for the declarative part of the \fIname\fR 
  317. class.
  318. .RE
  319.  
  320. \fBtemplate\fR <\fBclass\fR \fItype\fR [, \fIparms\fR]> \fIresult\fR \fIname\fR<\fItype\fR>::\fIfunction\fR { ... };
  321. .RS
  322. Defines a member function for the implementation part of the \fIname\fR class.
  323. .RE
  324.  
  325. \fBtemplate\fR <\fBclass\fR \fItype\fR [, \fIparms\fR]> \fIname\fR { \fIanything\fR };
  326. .RS
  327. Defines anything else associated with a template for the \fIname\fR class.
  328. .RE
  329. .DE
  330. This last form is used to define such things as \fBtypedef\fRs or friend
  331. functions of a parameterized class.  When this form is found before the class
  332. template, the contents are expanded before the class definition.  When this
  333. form is found after the class template, the contents are expanded as part of
  334. the class implementation.  Note that this form is not part of the parameterized
  335. type syntax described by Stroustrup [6].  Rather, it is something we found
  336. lacking in the original proposal and found very useful in several COOL
  337. container classes for defining predicate types for the class under C++ 2.0.
  338. Another use of this form is to provide automatic declarations of nested
  339. parameterized classes, that is, to declare a parameterized class for a class
  340. template which is itself derived from another parameterized class template.
  341.  
  342. Each variation of \fBtemplate\fR allows additional optional parameters
  343. with the following syntax:
  344. .DS I
  345. \fIparms\fR ::= \fItype name\fR [\fB=\fR \fIvalue\fR] [\fB,\fR \fIparms\fR]
  346. .DE
  347. where \fItype\fR is the type of the parameter, (such as, \fBclass\fR or
  348. \fBint\fR); \fIname\fR is the name of the parameter that is substituted when
  349. \fBtemplate\fR is expanded; and \fIvalue\fR is the default value of parameter
  350. \fIname\fR.
  351.  
  352. The following is an example of \fBtemplate\fR for the class,
  353. \fBVector<\fItype\fB>\fB.
  354. .DS I
  355. template <class Type> Vector {            // predicate functions
  356.     typedef int (*Vector_##Type##_Predicate) (const Type&, const Type&);
  357.     typedef Boolean (*Vector_##Type##_Compare) (const Type&, const Type&);
  358. };
  359. .DE
  360. .DS I
  361. template <class Type> class Vector<Type> {    // Parameterized Vector class
  362.   private:
  363.     Type* v;                        // Vector of pointer to Type
  364.     int num_elements;                    // Element count
  365.     int size;                            // Size of vector object
  366.   public:
  367.     Vector<Type> ();                    // Empty constructor
  368.     Vector<Type> (int);                    // Constructor with size
  369.     Vector<Type> (const Vector<Type>&);    // Constructor with reference
  370.     ~Vector<Type> ();                    // Destructor
  371.     inline Type& operator[](int n);            // Operator[] overload for Type
  372. .DE
  373. .DS I
  374.     ...                                // ... other member functions ...
  375. };
  376. .DE
  377. .DS I
  378. template <class Type>                    // Overload operator []
  379. inline Type& Vector<Type>::operator[] (int n) {
  380.     return this->v[n];
  381. }
  382. .DE
  383. .DS I
  384. template <class Type>                    // Constructor with size
  385. Vector<Type>::Vector<Type> (int n) {
  386.     this->v = new Type[n];
  387.     this->size = n;
  388.     this->num_elements = 0;
  389. }
  390.  
  391.  ...                                // ... other member functions ...
  392. .DE
  393. .NH 2
  394. An Initial Programmer Interface: DECLARE and IMPLEMENT
  395. .LP
  396. As stated earlier, a \fBtemplate\fR for a parameterized class is divided into a
  397. declarative part and an implementation part.  In our first attempt at
  398. implementing parameterized template support, the programmer creates instances
  399. of a parameterized class using \fBDECLARE\fR to expand the declarative part and
  400. \fBIMPLEMENT\fR to expand the implementation part.  \fBDECLARE\fR defines the
  401. parameterized class for a specific type and \fBIMPLEMENT\fR generates the
  402. member functions supporting this type-specific class.  \fBDECLARE\fR must be
  403. used in every file that includes or makes use of the parameterized class.
  404. \fBIMPLEMENT\fR must be used only once in the application for each type over
  405. which the class is parameterized; otherwise the linker will generate errors
  406. about multiple versions of the same member functions.  For example, to create a
  407. vector of doubles, the following would be used:
  408. .DS I
  409. #include <Vector.h>
  410. DECLARE Vector<double>;
  411. IMPLEMENT Vector<double>;
  412. Vector<double> vs(30);        
  413. .DE
  414. \fBDECLARE\fR expands to code which defines a vector class of doubles and its
  415. associated inline member functions.  \fBIMPLEMENT\fR causes a class definition
  416. with its associated member functions to be generated and expanded in the file.
  417. When compiled, this causes the class \fBVector_double\fR to be declared and
  418. defined. One drawback of the use of \fBIMPLEMENT\fR, however, is the fact that
  419. the \fIentire\fR class with all its member functions is generated and linked
  420. into the program image, even if the programmer only requires the use of two or
  421. three member functions. This problem can be avoided by the use of the COOL C++
  422. Control Program (\fBCCC\fR) discussed below. Continuing with the example above,
  423. the \fBtemplate\fR for the \fBVector<\fItype\fB>\fR class for doubles would
  424. expand to the following code:
  425. .DS I
  426.                                 // predicate functions
  427. typedef int (*Vector_double_Predicate) (const double&, const double&);
  428. typedef Boolean (*Vector_double_Compare) (const double&, const double&);
  429. .DE
  430. .DS I
  431. class Vector_double {                    // Parameterized Vector class
  432. private:
  433.     double* v;                        // Vector of pointer to double
  434.     int num_elements;                    // Element count
  435.     int size;                            // Size of vector object
  436. public:
  437.     Vector_double ();                    // Empty constructor
  438.     Vector_double (int);                    // Constructor with size
  439.     Vector_double (const Vector_double&);    // Constructor with reference
  440.     ~Vector_double ();                    // Destructor
  441.     inline double& operator[](int n);            // Operator[] overload for double
  442. .DE
  443. .DS I
  444.     ...                                // ... other member functions ...
  445. };
  446. .DE
  447. .DS I
  448.                                 // Overload operator []
  449. inline double& Vector_double::operator[] (int n) {
  450.     return this->v[n];
  451. }
  452. .DE
  453. .DS I
  454.                                 // Constructor with size
  455. Vector_double::Vector_double (int n) {
  456.     this->v = new double[n];
  457.     this->size = n;
  458.     this->num_elements = 0;
  459. }
  460.  
  461.  ...                                // ... other member functions ...
  462.  
  463. Vector_double vs(30);        
  464. .DE
  465. Declarations of nested parameterized types and the use of non-type arguments in
  466. a template definition are also supported. For example, it is possible to
  467. declare a vector of vectors of ints with \fBVector<Vector<int>>\fR.  In
  468. addition, a class template derived from another class template is supported,
  469. that is, a type parameter in one template class can be used to declare another
  470. class template of that type.  For example, the COOL 
  471. \fBAssociation<\fIT1\fR,\fIT2\fB>\fR class is
  472. a parameterized container class that takes two type arguments, \fIT1\fR and
  473. \fIT2\fR.  The header file for this class has the following templates.
  474. .DS I
  475. template <class T1, T2> Association {
  476.     DECLARE Pair<T1, T2>;                // Declare Pair object type
  477.     DECLARE Vector<Pair<T1, T2>>;        // Declare Vector of Pairs
  478. }
  479.  
  480.  ...                                // ...
  481. // Association<T1,T2> class definition here
  482.  
  483. .DE
  484. .DS I
  485. template <class T1, T2> Association {
  486.     IMPLEMENT Pair<T1, T2>;
  487.     IMPLEMENT Vector<Pair<T1, T2>>;
  488. }
  489. .DE
  490. By using \fBtemplate\fR in this manner, \fBDECLARE\fR for the
  491. \fBAssociation<\fIT1\fR,\fIT2\fB>\fR class invokes \fBDECLARE\fR on the correct
  492. types for the \fBPair<\fIT1\fR,\fIT2\fB>\fR and \fBVector<\fIType\fB>\fR
  493. classes.  Likewise, \fBIMPLEMENT\fR for the
  494. \fBAssociation<\fIT1\fR,\fIT2\fB>\fR class invokes \fBIMPLEMENT\fR for the
  495. \fBPair<\fIT1\fR,\fIT2\fB>\fR and \fBVector<\fIType\fB>\fR classes.
  496.  
  497. Non-type arguments as template parameters are used to provide guidelines to be
  498. used when a template is expanded. For example, the
  499. \fBN_Tree<\fINode\fR,\fIType\fR,\fInchild\fB>\fR class in COOL takes as
  500. arguments a node type (either static or dynamic), a type specifying the
  501. value-type each node will hold, and an argument that specifies the number of
  502. initial subtrees (or children) each node is to have.  The node argument is
  503. itself the name of a parameterized class and a nested parameterized template
  504. definition is automatically generated based upon the supplied type and number
  505. arguments. As such, a single template can be used to generate several different
  506. classes with different behaviors and features.
  507. .NH 2
  508. A Revised Programmer Interface: COOL C++ Control Program (CCC)
  509. .LP
  510. The \fBDECLARE\fR and \fBIMPLEMENT\fR macros discussed above were the first
  511. programmer interface implemented for parameterized template support.  We soon
  512. discovered, however, that this macro expansion mechanism had two serious
  513. problems. First, the type over which a class was parameterized would have to
  514. support all operators used in the template, even if not applicable or needed.
  515. For example, the COOL \fBList<\fIType\fB>\fR class has several member functions
  516. that use \fBoperator<\fR. However, if what the programmer needs is a list of
  517. window objects and does not ever use \fBList<\fIType\fB>\fR member functions
  518. that require \fBoperator<\fR, compile-time errors from the offending functions
  519. that got macro-expanded are nevertheless generated. Second, with the simplistic
  520. linkers available on many operating systems today, an application gets all of
  521. these member functions linked into the executable image.  Typically, an
  522. application uses only a small percentage of the member functions of a
  523. parameterized class.  The remaining unused member functions are useless
  524. overhead, increasing program size and memory requirements.
  525.  
  526. A revised programmer interface for parameterized templates was implemented to
  527. resolve these problems and centers around a new program to be used as the main
  528. interface between the user and the preprocessor/compiler in a make file. This
  529. program, the COOL C++ Control program (\fBCCC\fR), augments the standard
  530. \fBCC\fR script.  For most operations, user options and command line arguments
  531. are passed straight through to the underlying CC program.  However, when the
  532. \fB-X\fR option is specified, the \fBCCC\fR program goes to work in the
  533. following manner.  As Stroustrup[6] suggested, \fB-X"Foo<Bar>"\fR is used on
  534. the command line to indicate that the programmer wants to parameterize class
  535. \fBFoo<\fIType\fB>\fR over some type \fBBar\fR.  Additional options for include
  536. file search path and a user-defined library archive are required as described
  537. below.  \fBCCC\fR finds the header file(s) implementing class Foo and type Bar,
  538. then proceeds to define that type for the compiler.  It then \fIfractures\fR
  539. the implementation of this new type along template boundaries, placing each
  540. non-inline member function in a separate source file, compiling it, and putting
  541. the resulting object file in a user-specified library archive.  If a particular
  542. operator is not defined for the type over which the class is parameterized (as
  543. with the example of \fBoperator<\fR above), a compile time error for that one
  544. file is generated.  However, the remaining member functions, one in each
  545. fractured template, are still compiled and added to the user library.
  546.  
  547. For each parameterized class in an application, \fBCCC\fR fractures the
  548. parameterized class definition along template boundaries, causing each
  549. \fBtemplate\fR specifying a member function of the parameterized class to be
  550. compiled into a separate object file.  These separate object files are then
  551. added to an application-specific object library.  Since each member function is
  552. in its own object module in the library, only those member functions actually
  553. used in the application are linked into the final executable image. To use
  554. \fBCCC\fR, the programmer specifies a library name, one or more header files
  555. containing templates, and specific parameterized classes as command line
  556. arguments to \fBCCC\fR.  Other arguments are passed on unchanged to the C++
  557. compiler and system linker.  A single invocation of \fBCCC\fR can either
  558. process a parameterized class type or compile a C++ source file, but not both.
  559. For example,
  560. .DS I
  561. CCC -lapp -c List.h String.h -X "List<String>"
  562. .DE
  563. expands the template for a list of strings.  The resulting object files from
  564. the fractured parameterized \fBList<\fIType\fB>\fR class are stored in
  565. the library, \fBlibapp.a\fR.  The \fB-c\fR option is passed to the compiler to
  566. indicate that it should not continue with the link phase. The library archive
  567. \fBlibapp.a\fR is added to the list of libraries specified in the make file
  568. to be searched during the link step.
  569.  
  570. The net result is a library archive containing object files, each implementing
  571. one member function for the parameterized class and type. This process solves
  572. the two problems identified above with the use of the macros \fBDECLARE\fR and
  573. \fBIMPLEMENT\fR. First, operators not defined for a type cause compile-time
  574. errors on that one file.  Once a parameterized class has been implemented and
  575. provided in a library, compile errors will only occur when a type is selected
  576. that does not have all operators implemented. The user of the class will see
  577. these, and if the member function in question is required, s/he can add that
  578. necessary operator to the type class.  Second, only member functions actually
  579. used in an application are linked into the final executable image.
  580. .NH 2
  581. Future Improvements to CCC
  582. .LP
  583. \fBCCC\fR essentially provides a more sophisticated version of the
  584. \fBIMPLEMENT\fR macro discussed above. However, the programmer is still
  585. required to place the \fBDECLARE\fR macro in the appropriate files.  One
  586. option under consideration to resolve this problem is the use of a command line
  587. switch similar to the +e0/+e1 switchs on the AT&T cfront translator. Under this
  588. scenario, the equivalent of the +e0 option would be used to declare the type for
  589. a parameterized class and generate the inline member functions (as the
  590. \fBDECLARE\fR macro does) but not to generate the remaining member functions.
  591. The programmer would use the equivalent of the +e1 option on one source file to
  592. cause the remaining non-inline member functions to be generated and placed in a
  593. library archive.
  594.  
  595. A second problem with \fBCCC\fR concerns the specification of nested
  596. parameterized classes. A programmer should be able to use
  597. \fB-X"Vector<List<int>>"\fR on the command line to specify creation of nested
  598. parameterized classes.  Currently, \fBCCC\fR does not handle this case
  599. appropriately. A more sophisticated command line parser should be able to
  600. recognize and implement nested types before trying to expand the outer most
  601. parameterized class.
  602. .NH 1
  603. Conclusion
  604. .LP
  605. The COOL macro facility provides a mechanism to implement significant language
  606. features and extensions for C++ that are unavailable with current language
  607. implementations.  The macro facility is implemented in an enhanced preprocessor
  608. that is both efficient and portable, thus allowing for delivery of enhanced
  609. language features on many platforms. This macro extension is at the heart of
  610. the parameterized templates functionality. \fBCCC\fR is used in place of the
  611. normal procedure for controlling the compilation process.  It provides all of
  612. the functionality of the original \fBCC\fR program with additional support for
  613. the COOL preprocessor and parameterized type expansion.  Finally, the
  614. preprocessor provides an ideal mechanism for quickly prototyping and testing
  615. additional language functions and syntax without requiring access to or
  616. modification of a compiler.
  617. .NH 1 
  618. Status of COOL
  619. .LP
  620. Texas Instruments has been using the enhanced macro facility and the
  621. implementation of parameterized templates internally on several projects for
  622. the last year. Many classes and programs have been successfully designed and
  623. implemented, taking full advantage of the power of parameterized templates and
  624. the enhanced macro facility. In particular, we have found that the use of a
  625. class library supplying many basic parameterized container classes
  626. significantly increases the productivity of the programmer, enabling
  627. applications to be prototyped in a shorter time period than might otherwise be
  628. possible.  COOL is currently up and running on a Sun SPARCstation 1 (TM)
  629. running SunOS (TM) 4.x,
  630. .FS
  631. SunOS and SPARCstation 1 are trademarks of Sun Microsystems, Inc.
  632. .FE
  633. a PS/2 (TM) 
  634. .FS
  635. PS/2 is a trademark of International Business Machines Corporation.
  636. .FE
  637. model 70 running SCO XENIX\(rg
  638. .FS
  639. XENIX is a registered trademark of Microsoft Corporation.
  640. .FE
  641. 2.3, a PS/2 model 70 running OS/2 1.2, and a MIPS running RISC/os 4.0.  The
  642. SPARC and MIPS ports utilize the AT&T C++ translator (cfront) version 2.1 and
  643. the XENIX and OS/2 ports utilize the Glockenspiel translator 2.0a with the
  644. Microsoft C 6.0 compiler. 
  645.  
  646. The COOL preprocessor source code is available in compressed tar(1) format in
  647. the file /pub/cpp.tar.Z via anonymous FTP from CSC.TI.COM (128.247.159.141).
  648. Permission is granted to any individual or institution to use, copy, modify,
  649. and distribute this software, provided that all copyright statements and
  650. permission notices are maintained, intact, in all copies and supporting
  651. documentation. Texas Instruments Incorporated provides this software "as is"
  652. without express or implied warranty.
  653. .NH 1
  654. References
  655. .IP [1]
  656. Brian Kernighan and Dennis Richie,
  657. .I
  658. The C Programming Language,
  659. .R
  660. Second Edition, Printice-Hill, Englewood Cliffs, NJ, 1988.
  661. .IP [2]
  662. Mary Fontana, Martin Neath and Lamott Oren,
  663. .I
  664. COOL - A C++ Object-Oriented Library,
  665. .R
  666. Information Technology Group, Austin, TX, TI Internal Document, Original Issue January 1990.
  667. .IP [3]
  668. Texas Instruments Incorporated,
  669. .I
  670. C++ Object-Oriented Library User's Manual,
  671. .R
  672. Information Technology Group, Austin, TX, TI Internal Document, Original Issue January 1990.
  673. .IP [4]
  674. AT&T Incorporated,
  675. .I
  676. C++ Language System Release 2.0,
  677. .R
  678. AT&T Product Reference Manual Select Code 307-146, 1989.
  679. .IP [5]
  680. Guy L. Steele Jr,
  681. .I
  682. Common LISP: The Language,
  683. .R
  684. Second Edition, 1990.
  685. .IP [6]
  686. Bjarne Stroustrup, 
  687. .I
  688. Parameterized Types for C++,
  689. .R
  690. Proceedings of the USENIX C++ Conference, Denver, CO, October 17-21, 1988,
  691. pp. 1-18.
  692.