This chapter describes using code intended for the C++ 4 compilers with the C++ 5.0 compiler.
The compiler options for compatibility mode are (both versions mean the same thing):
-compat -compat=4
CC -compat -O myfile.cc mylib.a -o myprog
By default, some of the new C++ keywords are recognized as keywords in compatibility mode, but you can turn off most of these keywords with compiler options, as shown in the following table. Changing the source code to avoid the keywords is preferable to using the compiler options.
Table 2-1 Keywords in Compatibility Mode
Keyword |
Compiler option to disable |
---|---|
explicit |
-features=no%explicit |
export |
-features=no%export |
mutable |
-features=no%mutable |
typename |
cannot disable |
Keyword typename cannot be disabled. The additional new C++ keywords, described in Table 3-1, are disabled by default in compatibility mode.
The 5.0 compiler does a better job of enforcing some C++ language rules. It is also less permissive about anachronisms.
If you compile with C++ 4 and enable anachronism warnings, you might discover code that has always been invalid, but that much older C++ compilers accepted anyway. It was always explicit policy (that is, stated in the manuals) that the anachronisms would cease to be supported in future compiler releases. The anachronisms consist mainly of violating access (private, protected) rules, violating type-matching rules, and using compiler-generated temporary variables as the target of reference parameters.
The rules that previously were not enforced are as follows:
When initializing an object, or passing or returning a value of class type, the copy constructor must be accessible.
class T { T(const T&); // private }; void f1(T t) { } // Error, can't pass a T T f2() { T t; return t; } // Error, can't return a T
Solution: Make the copy constructor accessible, usually public.
The static storage class applies to objects, not to types.
static class C {...}; // Error, cannot use static here static class D {...} d; // OK, d is static
Solution: In this example, the static keyword does not have any meaning for class C and should be removed.
When allocating an object with new, the matching operator delete must be accessible.
class T { void operator delete(void*); // private public: void* operator new(size_t); }; T* t = new T; // Error, operator delete is not accessible
Solution: Make operator delete accessible, usually public.
Default parameter values on overloaded operators or on pointers to functions are not allowed.
T operator+(T t1, T t2 = T(0) ); // Error void (*fptr)(int = 3); // Error
Solution: You must write the code some other way, probably by providing additional function or function pointer declarations.
The function main must have a return type of int.
void main(){ ... } // error
Solution: Give main a return type of int. It is not necessary to add a return statement. If a return statement is present, it must return an int value.
Trailing commas in function argument lists are not allowed.
f(int i, int j, ){ ... } // error
Solution: Remove the extra comma.
Passing a const or literal value to a nonconstant reference parameter is not allowed.
void f(T&); extern const T t; void g() { f(t); // Error }
Solution: If the function does not modify its parameter, change the declaration to take a const reference (for this example, const T&). If the function modifies the parameter, you cannot pass it a const or a literal value. An alternative is to create an explicit nonconstant temporary and pass that instead. See "String Literals and char* " for related information.
A version of operator new or operator delete that is not a class member must not be declared static.
static void* operator new(size_t); // error
Solution: Make the function global.
If an object of enum type is initialized or assigned a value, that value must have the same enum type.
enum E { one = 1 }; E e1 = 1; // Error, can't use an int to intialize an E E e2 = E(1); // OK with cast
Solution: Use a cast.
Macros cannot be redefined to a different value without an intervening #undef.
#define count 1 #define count 2 // Error
Solution: Remove one of the #define statements, or put a #undef count statement before the second #define.
The old C++ syntax of implied base-class name in a member-initializer list is not allowed.
struct B { B(int); }; struct D : B { D(int i) : (i) { } // Error, should be B(i) };
If you allocate a const object with new, it must be initialized.
const int* ip1 = new const int; // Error const int* ip2 = new const int(3); // OK
const and volatile qualifiers on pointers must match properly when passing arguments to functions, and when initializing variables.
void f(char *); const char* p = "hello"; f(p); // Error: passing const char* to non-const char*
Solution: If the function does not modify the characters it points to, declare the parameter to be const char*. Otherwise, make a nonconstant copy of the string and pass that instead.