This chapter discusses the migration of working code from a C++ 3.0 or 3.0.1 compiler directly to the C++ 5.0 compiler.
The following keywords have been added to C++ since the C++ 3.0 compiler. If you use any of these as identifiers, you should change the names. As shown in Table 3-1, some keywords can be turned off in C++ 5.0.
bool, false, true const_cast, dynamic_cast, reinterpret_cast, static_cast explicit export mutable namespace, using typename wchar_t
The following list describes changes that must be made to code that was written for the C++ 3.0 compiler before compiling the code with the C++ 5.0 compiler.
K&R-style function definitions are no longer allowed. You must use prototype-style definitions.
int f(a) int a; { ... } // Error in C++ 5.0
You cannot set a global variable _new_handler by assignment. Call function set_new_handler() instead.
Global operator new() is always used when there is no in-class version. C++ 3.0 incorrectly used an outer-class version in preference to the global version. In the following example, C++ 3.0 would incorrectly use Outer::operator new to allocate space.
class Outer { public: void* operator new(size_t); class Inner { ... // No operator new }; }; Outer::Inner* p = new Outer::Inner; // Which operator new?
Typedef names cannot be used as struct (or class or union) tags. For example:
typedef struct { int x; } S; struct S b; // OK in C++ 3.0, error in C++ 5.0 S c; // Always OK
typedef struct S { int x; } S; struct S b; // Always OK S c; // Always OK
You cannot redefine a name from an outer scope once it has been used in a class. Such redefinition is disallowed by the C++ standard, since it can be disastrous, but the C++ 3.0 compiler did not detect the situation. The C++ 5.0 compiler makes it an error. For example:
typedef int T; class C { T iv; // type int typedef float T; // redefine T -- error in C++ 5.0 T fv; // type float };
The C++ 3.0 compiler had a bug that allowed a pointer to a function taking unspecified parameters to act in some circumstances as a "universal" pointer-to-function, as in the following example. The C++ rule is that function pointer types must match.
typedef (*pfp)(int,char); typedef (*ufp)(...); int foo(int,char); pfp p = (ufp)foo; // Allowed by 3.0, error in 5.0
Comma-expressions are not allowed in null pointer constants. Although a literal zero is a null pointer constant, an expression such as (anything, 0) is not:
int f(); char* g() { return (f(), 0); // OK in 3.0, error in 5.0 // should be: // return (f(), (char*)0); // OK // or two statements: // f(); // return 0; }
Classes with base classes cannot be initialized with aggregate-initialization syntax. The C++ 3.0 compiler allowed this if no virtual functions were present. You should write a constructor for the class instead.
struct Base { int i; }; struct Derived : Base { int j; }; Derived d = {1, 2}; // OK with 3.0, error in 5.0
The Sun C++ compiler's implementation of templates is different from that of AT&T's Cfront compiler. Cfront uses link-time instantiation, which uses the following algorithm:
Compile all user source files.
Using the prelinker, ptlink, link all object files created in Step 1 into a partially linked executable.
Examine the link output and instantiate all undefined functions for which there are matching templates.
Link all created templates along with the partially linked executable files from Step 2.
As long as there are undefined functions for which there are matching template functions, repeat Steps 3 through 4.
Perform the final pass of the link phase on all created object files.
The main advantage of link-time instantiation is that no special outside support is required to handle specializations (user-provided functions intended to override instantiated template functions). Only those functions that have not been defined in the user source files become targets of instantiation by the compiler.
The two main disadvantages of link-time instantiation are:
Because an instantiation takes place during the link phase, all error messages resulting from an instantiation are deferred until after its use. As a result, there is no helpful traceback of where the error might have occurred.
Repetitive calls to the prelinker can dramatically increase the link time.