C++ Migration Guide

Templates

The C++ standard has some new rules for templates that make old code nonconforming, particularly code involving the use of the new keyword typename. The 5.0 compiler does not yet enforce these rules, but does recognize this keyword. Template code that worked under the 4.2 compiler probably continues to work, although the 4.2 version accepted some invalid template code. You should migrate your code to the new C++ rules as development schedules permit, since future compilers will enforce the new rules.

Resolving Type Names

The C++ standard has new rules for determining whether an identifier is the name of a type. The following example illustrates the new rules:


typedef int S;
class B { ... typedef int U; ... }
template< class T > class C : public B {
    S    s; // OK
    T    t; // OK
    U    x; // 1 No longer valid
    B::U y; // 2 No longer valid
    T::V z; // 3 No longer valid
};

The new language rules state that no base class is searched automatically to resolve type names in a template, and that no name coming from a base class or template parameter class is a type name, unless it is declared to be so with the keyword typename.

The first invalid line (1) in the code example tries to inherit U from B as a type without the qualifying class name and without the keyword typename. The second invalid line (2) correctly modifies the type with the name of the base class, but the typename modifier is missing. The third invalid line (3) uses type V coming from the template parameter, but omits the keyword typename. The definition of s is valid because the type doesn't depend on a base class or member of a template parameter. Similarly, the definition of t is valid because it uses type T directly, a template parameter which must be a type.

The following code shows the correct implementation:


typedef int S; 
class B { ... typedef int U; ... } 
template< class T > class C : public B {
    S             s; // OK
    T             t; // OK
    typename B::U x; // OK
    typename B::U y; // OK
    typename T::V z; // OK
};

Converting to the New Rules

A problem for migrating code is that typename was not previously a keyword. If existing code uses typename as an identifier, you must first change the name to something else.

For code that must work with old and new compilers, you can add statements that are similar to the following example to a project-wide header file.


#ifdef TYPENAME_NOT_RECOGNIZED
#define typename
#endif

The effect is to conditionally replace typename with nothing. When using older compilers (such as Sun C++ 4.2) that do not recognize typename, add -DTYPENAME_NOT_RECOGNIZED to the set of compiler options in your makefile.

Explicit Instantiation and Specialization

In the ARM, and in the 4.2 compiler, there was no standard way to request an explicit instantiation of a template using the template definition. The C++ standard, and the 5.0 compiler in standard mode, provide a syntax for explicit instantiation using the template definition; the keyword template followed by a declaration of the type. For example, the last line in the following code forces the instantiation of class MyClass on type int, using the default template definition.


template<class T> class MyClass {
    ...
};
template class MyClass<int>; // explicit instantiation 

The syntax for explicit specializations has changed. To declare an explicit specialization, or to provide the full definition, you now prefix the declaration with template<>. (Notice the empty angle brackets.) For example:


// specialization of MyClass
class MyClass<char>;         // old-style declaration
class MyClass<char> { ... }; // old-style definition
template<> class MyClass<char>;         // standard declaration
template<> class MyClass<char> { ... }; // standard definition

The declaration forms mean that the programmer has somewhere provided a different definition (specialization) for the template for the provided arguments, and the compiler is not to use the default template definition for those arguments.

In standard mode, the 5.0 compiler accepts the old syntax as an anachronism. The 4.2 compiler accepts the new specialization syntax, but does not treat code using the new syntax correctly in every case. (The standard changed after the feature was put into the 4.2 compiler.) For maximum portability of template specialization code, you can add statements similar to the following to a project-wide header:


#ifdef OLD_SPECIALIZATION_SYNTAX
#define Specialize
#else
#define Specialize template<>
#endif

Then you would write, for example:

Specialize class MyClass<char>; // declaration

Template Repository

The Sun implementation of C++ templates uses a repository for template instances. The C++ 4.2 compiler stored the repository in a directory called Templates.DB. The Sun C++ 5.0 compiler, by default, uses directories called SunWS_cache and SunWS_config. SunWS_cache contains the working files and SunWS_config contains the configuration files, specifically, the template options file (SunWs_config/CC_tmpl_opt). (See the C++ Users' Guide.)

If you have makefiles that for some reason mention repository directories by name, you need to modify the makefiles. Furthermore, the internal structure of the repository has changed, so any makefiles that access the contents of Templates.DB no longer work.

In addition, standard C++ programs probably make heavier use of templates. Paying attention to the considerations of multiple programs or projects that share directories is very important. If possible, use the simplest organization. You must compile only files belonging to the same program or library in any one directory. The template repository then applies to exactly one program. If you compile a different program in the same directory, clear the repository by using CCadmin -clean. See C++ User's Guide for more information.

The danger in more than one program sharing the same repository is that different definitions for the same name might be required. This situation cannot be handled correctly when the repository is shared.

Templates and the Standard Library

The C++ standard library contains many templates, and many new standard header names to access those templates. The Sun C++ standard library puts declarations in the template headers, and implementation of the templates in separate files. If one of your project file names matches the name of a new template header, it is possible to pick up the wrong implementation file, and cause numerous, bizarre errors. Suppose you have your own template called vector, putting the implementation in a file called vector.cc. Depending on file locations and command-line options, it is possible for the compiler to pick up your vector.cc when it needs the one from the standard library, or vice-versa. When the export keyword and exported templates are implemented in a future compiler version, the situation will be worse.

There are two recommendations for preventing current and future problems: