|
|
Microsoft Windows NT Build 297 06-28-1992
Microsoft Foundation Classes Microsoft Corporation Technical Notes #4 : Template Classes and MFC This note describes MFC template class issues and the MFC "templdef" template expansion sample code. ============================================================================= The Problem =========== There has long been recognized within the C++ community the need for template classes -- classes that can be instantiated based on an exact type specified by the user. A common example would be a linked list class -- a linked list of what type of object? With template classes the user of the class can specify that: "I want a linked list of CFoo objects." ----------------------------------------------------------------------------- The templdef sample =================== While a syntax for template classes has been generally agreed-upon within the C++ community, exact details have not been worked out. We found it useful to provide template classes to the user in the interim. The approach decided upon was to use a syntax for our template classes based on that generally used within the C++ community. This syntax is then expanded and modified slightly by a simple template expander called "templdef." For this expansion the user specifies a "typedef'ed" name to be used as an alternative to the template_class<type_specifier> class name. With this approach the Foundation user can begin to write template classes following the generally agreed-upon syntax for C++ templates. This code can be ported to the eventual final agreed-upon syntax when the ANSI C++ report is issued. Also, the Foundation user can read the Foundation template classes as general examples of how one writes templates. And the templdef source code provides an example of how one can use the Foundation classes. In order to provide easily readable output from the templdef template expander, we have chosen to leave comments in the expanded output, and to substitute-in textually the type parameters the user specifies. If the user desires to expand template classes over complicated types, use of typedef'ed type names is suggested for template parameters. We advise users wanting to experiment with template classes and templdef should first write and completely debug a non-template version of their class. For example, first write a linked-list-of-CFoos class. When you have that working, then generalize your linked-list-of-CFoos class to a linked-list-of-whatever template class. By taking this approach, you introduce the complicating factor of "template <class CXyz>" syntax *after* you have an already working linked-list class. Finally, you should expect some small changes between the template classes you write today, and the final syntax agreed upon by the ANSI-C++ committee. A good way to get started is by examining the .ctt template classes provided with Foundation (found in mfc\sample\templdef subdirectory). The mkcoll.bat file gives examples of the command line syntax of the templdef tool. The general form of the command line syntax is modeled after a C++ typedef of the equivalent template class. As a hypothetical exammple: typedef CArray<CString> CStringArray; becomes: templdef "CArray<CString> CStringArray" array.ctt strarray.h strarray.cpp Note: The actual Foundation template classes are slightly more complicated than this example, taking a number of boolean constant template parameters which allow several slightly different flavors of arrays to be expanded. ----------------------------------------------------------------------------- Template source formatting ========================== A source file containing a templdef template class is divided into three sections. The first section consists of comments, usage instructions, copyright notices and the like. This first section is stripped by templdef and is not emitted. The second section starts with a special: //$DECLARE_TEMPLATE directive, after which the template class declaration appears. templdef processes this section to result in the output .h file. After the declaration section comes a special: //$IMPLEMENT_TEMPLATE directive followed by any member function definitions required by the template class. This final section is processed into the resulting .cpp output file. Friend functions, static member definitions, and the like can be included as needed in these sections. Other than #if/#else/#endif sections expanded on a template parameter (see next section), preprocessor commands are left unexpanded in the output files. This permits additional processing by the native compiler preprocessor. One restriction of the templdef implementation is that the first occurance of a template declaration (typically *the* template class declaration) defines *all* name-wise correspondences between template formal parameters and actual parameters throughout the template class file. Thus template parameter names must be used consistently throughout all template declarations and definitions in the template class file. This approach is consistent with the fact that you are expanding on only one particular, out of n possible, template possibilities. ----------------------------------------------------------------------------- Template parameters and special #if/#else/#endif processing =========================================================== Templdef template parameters can either be types, or can be compile-time constant expressions. In particular, if a template parameter is "0" or "1", then templdef will evaluate (only) #if/#else/#endif statements based on that constant parameter, and emit only those lines of code corresponding to the true condition. Again, see mkcoll.bat and the Foundation template classes for examples of how to use this feature. The #if/#else/#endif expansion depends on having exactly the manifest constant "1" or "0" as a template parameter. For example, if you were to say "TRUE" or "FALSE" instead, then templdef would leave in the #if/#else/#endif expressions for the preprocessing phase of the compiler to expand later. Also, this templdef evaluation does not take into account nested #if/#else statements -- either make sure your expansion corresponds to an inner-most nesting and use "0" or "1" as your boolean constant template parameter, or say "FALSE" or "TRUE" and let the compiler's preprocessing phase do the #if/#else/#endif expansion later. Another limitation on templdef's capabilities in this area is that it expects #if/#else/#endif statements to be written following the common convention of no intervening space after the '#' sign. If you need to write # .... if / # .... else / # .... endif then let the compiler's preprocessor handle the job instead. -----------------------------------------------------------------------------
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.