|
The ANSI/ISO C++ International Standard redefines the rules, syntax, and features of C++
language. If your existing code contains any of the standards based keywords as variable
names, you must change the variable names when you convert your program to an HP aC++
program.
In addition to keyword changes, there are changes in the following:
C++ Semantics
Following lists the differences in code behavior when you migrate from HP C++ to HP aC++:
Note: These differences can occur inspite of compiling your code without errors.
Implicit Typing of Character String Literals
HP C++ implicitly types character string literals as char *. HP aC++, in accordance with
the ANSI/ISO C++ International Standard, types character string literals as const char *.
This difference affects function overloading resolution.
Example:
In the following code, HP aC++ calls the first function a; cfront calls the second.
void a(const char *);
void a(char *);
f() {
a("A_STRING");
}
To prevent existing code from breaking, assign a string literal to a non-const pointer as shown in the following example:
char *p = "B_STRING";
Also, you cannot convert const char * to char * in a conditional expression in this context.
Example:
char *p = f() ? A : B;
In such a scenario, you must change the code as in the following example:
const char *p = f() ? A : B;
or
char *p = const_cast(f() ? A : B);
Overload Resolution Ambiguity of Subscripting Operator
HP C++ and HP aC++ have different overload resolution models. When you migrate to HP
aC++, you may see an overload resolution ambiguity for the subscripting operator. The
following code illustrates the problem:
struct String {
char& operator[](unsigned);
operator char*();
// ...
};
void f(String &s) {
s[0] = '0';
}
HP C++ accepts the above code, selecting String::operator[](unsigned) rather than the
user-defined conversion, String::operator char*(), followed by the built-in
operator[].
Compiling the code with HP aC++ produces the following error:
Error 225: "c.C", line 8 # Ambiguous overloaded function call;
more than one acceptable function found. Two such functions
that matched were "char &String::operator [](unsigned int)"
["c.C", line 2] and "char &operator [](char *,int)"
[Built-in operator].
s[0] = '0';
The error message appears because the compiler cannot choose between:
-
Not converting s, but converting 0 from type int to type unsigned int;
this implies using the user-provided subscript operator[]
-
Converting s to type char* (using the user-defined conversion operator), but not
converting 0; this corresponds to using the built-in subscript operator[].
In order to disambiguate this situation in favor of the user-provided subscript operator[],
make the conversion of 0 in alternative (1.) no worse* than the conversion of 0 in alternative
(2.).
Because the subscript type for the built-in operator[] is ptrdiff_t (as defined in
<stddef.h>), this is also the type that should be used for user-defined subscript operators.
Replace the previous example by:
#include <stddef.h>
struct String {
char& operator[](ptrdiff_t);
operator char*();
// ...
};
void f(String &s) {
s[0] = '0';
}
*worse is relative to a ranking of conversions as described in the ANSI/ISO C++
International Standard on overloading. In general, a user-defined conversion is
worse than a standard conversion, which in turn is worse than no conversion at all.
The complete rules are more fine grained.
Execution Order of Static Constructors in Shared Libraries
In HP C++ (cfront), static constructors in shared libraries listed on the link-line are executed,
by default, in left-to-right order. HP aC++ executes static constructors in depth-first order;
that is, shared libraries on which other files depend are initialized first. Use the -depth
command-line option on the CC command line for enhanced compatibility with HP aC++.
In addition, HP aC++ reverses the initialization order of .o files on the link-line. To aid in
migration, you can group all .o files together and all .so files together.
Example:
aCC file1.o file2.o lib1.so lib2.so lib3.so
In this scenario, cfront would initialize file2.o first, and then file1.o, while HP aC++
initializes file1.o and then file2.o. You must take this into account in your cfront code to
avoid link problems with HP aC++.
More Frequent Inlining of Inline Code
HP C++ does not inline some functions even when you request for it. This happens when the
function is too complex. If you use the +w option, the compiler displays a message whenever it
does not inline a requested function.
HP aC++ almost always inlines functions for which you have specified the inline keyword.
C++ Syntax
When you migrate from HP C++ to HP aC++, in addition to changes related to standards
based keywords, you may need to make changes to your source code in the following areas:
Explicit int Declaration
In HP C++, you do not need to explicitly specify int types. In HP aC++, you must explicitly
declare int types. This change reduces ambiguity among expressions involving function-like
casts and declarations.
Example:
The following code is valid in HP C++:
void f(const parm);
const n = 3;
main()
The equivalent, valid HP aC++ code follows:
void f(const int parm);
const int n = 3;
int main()
for Statement - New Scoping Rules
In HP C++, variables declared in the initializer list are allowed after the for statement. In
the ANSI/ISO C++ International Standard, variables declared in the initializer list are not
allowed after the for statement. HP aC++ provides this functionality when you specify the
following aCC command-line option:
-WC,-ansi_for_scope,on
If you do not specify this option, (or you specify the -WC,-ansi_for_scope,off option), by
default, the new rules do not take effect.
In this scenario, HP aC++ provides this standard functionality as an option to ease conversion
of existing code to the standard. No code change is currently required.
Future plans are to make the ANSI/ISO C++ International Standard syntax the default. HP
recommends that you correct your code, by moving the declaration of the for loop variable to
its enclosing block.
Example:
The following code currently compiles without errors with HP C++ and HP aC++. In the
future, HP aC++, will generate an error.
int main(int argc) {
for (int i = 1; i < argc; ++i) {
}
for (i = 0; i < argc; ++i) {
}
}
Correct the code as follows:
int main(int argc) {
int i;
for (i = 1; i < argc; ++i) {
}
for (i = 0; i < argc; ++i) {
}
}
struct as Template Type Parameter is Permitted
In HP C++, an error is generated when a struct is used as a template type parameter. In HP
aC++, when a struct is used as a template type parameter, it is correctly compiled, in
accordance with draft standard syntax. This is a new feature.
Example:
template class A {
public:
struct T a;
};
struct B {};
A b;
The following error is displayed when you compile this code with HP C++:
CC: "DDB4325.C", line 3: error: T of type any redeclared as struct (1479)
This code compiles without error with HP aC++.
Base Template Class Reference Syntax Change
In HP C++, you can reference a member of a base template class without qualifying the
member. In HP aC++, when you reference a member of a base template class, you must
qualify the member by adding this->.
Adding this-> defers name resolution until instantiation. This allows the compiler to find
members in template base classes. However, it prevents the compiler from finding names
declared in enclosing scopes.
Example:
template class BaseT {
public:
T t;
int i;
};
template class DerivedT : public BaseT {
public:
void foo1 () { t = 1; i = 1; } // warning 721
// t and i could be global.
void foo2 () { this->t = 2; this->i = 2; } // Correct syntax, no warning.
};
DerivedT d; // Here is the point of instantiation.
Tokens after #endif
In HP C++, any character that follows the #endif preprocessor statement causes a warning
and is ignored. In HP aC++, characters following the #endif preprocessor statement cause an
error and the program does not compile. To change this, remove all characters following all
#endif preprocessor statements or put the token in comments.
Example:
Compiling the following code with HP C++ causes a warning. Compiling with HP aC++
generates an error.
int main(){
#ifdef FLAG
int i;
i=1;
#endif FLAG
}
To compile with HP aC++, change the code to:
int main(){
#ifdef FLAG
int i;
i=1;
#endif //FLAG
}
overload not a Keyword
In HP C++, using the overload keyword to specify a function as an overloaded function
causes an anachronistic warning and is ignored. In HP aC++, using the overload keyword
causes an error and the program does not compile. To change this, remove all occurrences of
the overload keyword.
Example:
Compiling the following code with HP C++ causes a warning. Compiling with HP aC++
generates an error stating that overload is used as a type, but has not been defined as a type.
int f(int i);
overload int f(float f); // Remove the word overload.
int main () {
return 1;
}
Dangling Comma in enum
In HP C++, a comma following the last element in an enum list is ignored. In HP aC++, a
comma following the last element in an enum list generates an error. To avoid this error,
remove the comma after the last element.
Example:
enum Colors { red,
orange,
yellow,
green,
blue,
indigo,
violet, // This comma is illegal.
};
Static Member Definition Required
In HP C++, you can declare a static member and not define it. However, in HP aC++, you
cannot do so. You must define the declared static data member.
Example:
Compiling and linking the following code on HP C++ gives no warning nor error. Compiling
the code on HP aC++ gives neither a warning nor an error. Linking the resulting object file
generates a linker (ld) error that states that there are unsatisfied symbols.
class A {
public:
static int staticmember;
};
// int A::staticmember=0; // This would fix the problem.
int main ()
{
A::staticmember=1;
}
Declaring friend Classes
In HP C++, you can declare friend classes without the class keyword. In HP aC++,
declaring friend classes without the class keyword generates an error. To change this, add
the class keyword to all friend class declarations.
Example:
Compiling the following code on HP C++ does not generate a warning or an error. Compiling
the code on HP aC++ generates an error stating that the friend declaration for B is not in the
right form for either a function or a class.
class foo{
public:
friend bar; // Need to say: friend class B
};
int main (){
return 1;
}
Incorrect Syntax for Calls to operator new
In HP C++, you can use incorrect syntax to call operator new. In HP aC++, an error is
generated when incorrect syntax for operator new is used. To change this, add parentheses
around the use of operator new. This code compiles correctly with both HP C++ and HP
aC++.
Example:
Compiling the following code on HP C++ does not generate a warning or an error. Compiling
the code on HP aC++ generates errors stating operator expected instead of new and
undeclared variable operator S.
struct S {
int f();
};
int g() {
return new S->f();
}
// int g() { return (new S)->f();} // This would fix the problem.
int S:: f( ) {
return 1;
}
main() {
return 1;
}
Using :: in Class Definitions
In HP C++, you can declare members of classes inside the class using the following incorrect
syntax:
class_name::member_name
In HP aC++, this incorrect syntax is considered an error. You must remove the class_name::
specification from the member definition.
Example:
Compiling the following code on HP C++ does not generate a warning or an error. Compiling
the code on HP aC++ generates an error stating that you cannot qualify members of class X
in the class definition.
class X{
int X::f();
// int f(); // This would fix the problem and
// run successfully on both compilers.
>
int main(){
}
Duplicate Formal Argument Names
In HP C++, duplicate formal argument names are allowed. In HP aC++, duplicate formal
argument names generate an error. To avoid this, use unique formal parameter names.
Example:
The following code compiles with HP C++. With HP aC++, an error is generated stating that
symbol aParameter has been redefined and where it was previously defined.
int a(int aParameter, int * aParameter);
Ambiguous Function or Object Declaration
In HP C++, an ambiguous function or object declaration compiles without warning, assuming
an object declaration. In HP aC++, an ambiguous function or object declaration generates an
error. To change this, change the code to remove the ambiguity.
Example:
struct A {A(int);};
struct B {B(const A &); void g();};
void f(int p) {
B b(A(p)); // Declaration of function or object?
b.g(); // Error?
}
The ambiguity in the example code is whether b is declared as:
- A function with one argument (named p) returning an object of type B.
- An object of type B initialized with a temporary object of type A.
HP C++ compiles this code successfully and assumes b is an object. Compiling the code with
HP aC++ generates the following error:
Error: File "objDeclaration.c", Line 5
Left side of '.' requires a class object; type found was a function 'B (A)'.
Did you try to declare an object with a nested constructor call?
Such a declaration is interpreted as a function declaration B b(A)
[File "objDeclaration.c, Line 4].
Modify the code to the following to successfully compile it with both compilers:
struct A {A(int);};
struct B {B(const A &); void g();};
void f(int p) {
B b = A(p); // declaration of object
b.g(); // method call
}
Overloaded Operations ++ and --
You must use the overloaded operations ++ and -- correctly. These operations require a
member function with one argument. If the function has no argument, a warning is issued
and a postfic is assumed in HP C++.
In HP aC++, the inconsistency between the overloaded
function usage and definition is considered an error. To avoid this error, change the class
definition so that each overloaded function definition has the correct number of arguments.
Example:
class T {
public:
T();
const T& operator++ ();
};
int main () {
T t;
t++;
}
Compiling the above code with HP C++ generates the following warning:
CC: "pre.C", Line 8: warning: prefix ++/-- used as postfix (anachronism) (935)
Compiling the code with HP aC++ generates the following error:
Error 184: File "pre.C", Line 8
Arithmetic or pointer type expected for operator '++'; type found was 'T'.
To compile the code with HP C++ or HP aC++ use the following class definition:
class T {
public:
T();
const T& operator++ (); // prefix old style postfix definition
const T& operator++ (int); // postfix
};
Reference Initialization
Illegal reference initialization is no longer allowed. In HP C++, a warning is generated stating
that the initializer for a non-constant reference is not an lvalue (anachronism). In HP aC++,
an illegal initialization of a reference type generates an error and the program does not
compile. To avoid this error, use a constant reference.
Example:
void f() {
char c = 1;
int & r = c;
}
Compiling the above code with HP C++ generates the following warning:
C: "nonConstRef.C", line 6: warning: initializer for non-const
reference not an lvalue (anachronism)( (235)
Compiling the code with HP aC++ generates the following error:
Error: File "nonConstRef.C", Line 6
Type mismatch; cannot initialize a 'int &' with a 'char'.
Try changing 'int &' to 'const int &'.
For successful compilation with both compilers, change the code to the following:
void f() {
char c = 1;
const int & r = c;
}
Using operator new to Allocate Arrays
In HP C++, operator new is called to allocate memory for an array. In HP aC++, operator
new [] is called to allocate memory for an array.
Example:
The following code compiles without error on HP C++.
typedef char CHAR;
typedef unsigned int size_t;
typedef const CHAR *LPCSTR, *PCSTR;
typedef unsigned char BYTE;
void* operator new (size_t nSize, LPCSTR lpszFileName, int nLine);
static char THIS_FILE[] = "mw2.C";
int main() {
BYTE *p;
p = new(THIS_FILE, 498) BYTE[50];
}
On HP aC++, the following error is generated:
Error: File "DDB4269.C", Line 10
Expected 1 argument(s) for void *operator new [ ](unsigned int); had 3 instead.
Parentheses in Static Member Initialization List
In HP C++, redundant parentheses are allowed in a static member initialization list. In HP
aC++, redundant parentheses in a static member initialization list generate an error and the
program does not compile. You must remove the redundant parentheses to compile the
program with both compilers.
Example:
class A {
public:
int i;
static int (A::*p);
};
int (A::*(A::p)) = &(A::i);
Compiling this code HP aC++ generates the following error:
Error: File "DDB4270.C", Line 7
A pointer to member cannot be created from a parenthesized
or unqualified name.
To successfully compile the code, remove the parentheses from the last line.
class A {
public:
int i;
static int (A::*p);
};
int (A::*(A::p)) = &A::i;
&qualified-id Required in Static Member Initialization List
In HP C++, you can use an unqualified function name in a static member initialization list. In
HP aC++, an unqualified function name in a static member initialization list causes an error
and the program does not compile. Use the unary operator & followed by a qualified-id in the
member initialization list. The resulting code compiles correctly with HP C++ and HP aC++.
Example:
class A {
public:
int i;
int j();
static int (A::*p)();
};
int (A::*(A::p))() = j;
Compiling this code with HP aC++ generates the following error:
Error: File "DDB4270A.C", Line 7
Cannot initialize 'int (A::*)()' with 'int (*)()'.
To successfully compile with HP C++ and HP aC++, change the initialization list in line 7 to
&A::j;
class A {
public:
int i;
int j();
static int (A::*p)();
};
int (A::*(A::p))() = &A::j;
Non-constant Reference Initialization
In HP C++, if you do not initialize a non-constant reference with an lvalue, an anachronistic
warning is issued and compilation continues. In HP aC++, an error is issued if you do not use
an lvalue for a non-constant reference initialization. Use an lvalue for the reference
initialization, or define the reference as a const type.
Example:
void f(int &);
int main () {
f(3);
return 0;
}
Compiling this code with HP C++ generates the following warning:
CC: "DDB04313A.C", line 4: warning: temporary used for non-const int & argument;
no changes will be propagated to actual argument (anachronism) (283)
Compiling the above code with HP aC++ generates the following error:
Future Error: File "DDB04313A.C", Line 4
The initializer for a non-constant reference must be an lvalue.
Try changing 'int &' to 'const int &'.
To successfully compile the code with either compiler, use one of the two alternatives shown
below:
void f(const int &); // Use a constant reference.
int main () {
f(3);
return 0;
}
void f(int &);
int i;
int main () {
i=3;
f(i); // Use an lvalue for reference initialization.
return 0;
}
Digraph White Space Separators
HP C++ does not support alternative tokens (digraphs). In HP aC++, digraphs are supported
and legal C++ syntax can be considered an error because of digraph substitution. Insert a
blank between two characters of the digraph.
Example:
C<::A> a;
The characters <: are one of the alternative tokens (digraphs) for which HP aC++ performs a
substitution. In this case, <: becomes [. The statement to be compiled becomes C[:A a;,
which produces many compilation errors.
To successfully compile this program with either compiler, insert a blank between < and :.
C< ::A> a;
|