![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
C++ Language Support This section attempts to list some of the language features that are and are not supported by Apex C++. These lists may change in future releases of the compiler. There are many smaller language features that are not listed here.
The following topics are covered in this chapter
- Supported language features
- Unsupported language features
- Anachronistic constructs
- Options that affect the language
- C++ standard library
Supported language featuresApex C++ supports virtually all language features that are listed in the Annotated C++ Reference Manual (ARM). The following language features that have been added by the C++ committee since then are also supported:
- New keywords and digraphs. All C++ keywords (except for export) are recognized, even if the corresponding feature is not implemented. Digraphs (e.g. <% and %:) are fully supported.
- Exception handling.
- Namespaces.
- Run-time type information (type_info and typeid).
- New cast notation (dynamic_cast, static_cast, reinterpret_cast, and const_cast)
- The built-in boolean type bool.
- Relaxed restrictions on the return type of virtual functions (covariant return values).
- Operator overloading on enumerations.
- Overloading of operators new[] and delete[].
- wchar_t is a built-in keyword representing a distinct type.
- Declarations in conditional expressions.
- Mutable class members.
- Explicit constructors.
- Implicit conversions from (T **) to (const T * const *), and similar pointer conversions.
- Conditional statements introduce a new block scope.
- Enumerations are not integral types.
- The lifetime of a compiler-generated temporary object lasts to the end of the full-expression in which the temporary is created.
- The scope of a declaration in a for-init-statement is restricted to the for-statement.
- A derived class constructor may explicitly initialize an inherited virtual base.
- T() has a specified value for every type T.
- For any type T, including built-in types and classes without a user-defined destructor, explicitly calling the destructor (~T) is supported.
- A function can be declared pure virtual in a derived class even if it is already defined in a base class.
- new T[0] returns a unique pointer.
- Member bitfields may not be declared static.
- A class may declare a static data member with an incomplete type.
- Expressions of the form a.::B::c and p->::B::c are supported.
- An enumerator may be accessed with a . or -> operator.
- Default return value of 0 from main.
- The left hand side of a . or -> operator should always be evaluated, even if the expression refers to a static member.
- Compile-time member constants.
- Function try blocks.
- Placement delete.
Unsupported language featuresThese language features are currently not supported, but will be supported in some future release of the compiler.
- Templates are supported as defined in the ARM, along with some additional features, such as default values for template parameters. Newer template features that are not supported include member function templates of non-template classes, explicit instantiations, partial specialization, template parameters with reference type, explicit template argument specification for function templates, and default non-template parameters for function templates.
- The keywords typename and export.
- extern inline functions.
Anachronistic constructsSome language features that used to be legal C++ are still supported, but result in anachronism messages being generated by the compiler. These messages may be changed to errors in some future release of the compiler, so they should be avoided.
- Applying ++ and -- operators to enum types.
- Initializing a non-const reference with a non-lvalue.
- User-defined conversion operators to type void.
- Return type other than int for the function main.
- Undefined character escape sequences.
- Assigning an integral type to an enum.
- Default parameters for overloaded operators or pointers to functions.
- Using a count in a delete[] expression.
- Allocating uninitialized const objects using new.
- Initializing a reference with a NULL value.
- Multiple pointer declarators in a user-defined conversion operator.
- Declaring a function to be extern and then defining it inline.
- A goto statement that jumps past the initialization of a variable.
- Use of implicit int.
- Use of postfix ++ or -- operators when only the prefix versions are defined.
Options that affect the languageThere are a number of command-line options (see Invocation Options) that affect the language that the C++ compiler will accept. Those options and their effects on the language are explained in detail here.
Turns off the keywords and, and_eq, bitand, bitor, compl, not, not_eq, or, or_eq, xor, and xor_eq. They are treated as regular identifiers instead. No functionality is lost with this option, because these keywords are just synonyms for the tokens &&, &=, &, |, ~, !, !=, ||, |=, ^, and ^= respectively.
With this option, bool, true, and false are not keywords, but are ordinary identifiers. This may be useful when porting code that defines its own boolean type with the name bool. This option also suppresses the definition of the preprocessor macro _HAS_BOOL_, which is normally defined. Users may want to use this macro to conditionalize the definition of their own boolean type, so that the same code will work whether or not the compiler supports the built-in boolean type.
Note that the built-in boolean type still exists, even if -nobool is used. The identifiers __bool, __true, and __false are always keywords and always refer to the built-in boolean type, with or without -nobool.
-nobool is not supported in conjunction with -newlib. The two options may not be used together.
Turns off all support for exception handling. Use of the keywords throw (other than in a function exception specification), try, or catch results in a warning. Catch clauses of try blocks and function exception specifications are parsed for semantic correctness, but are otherwise ignored and do not result in any code being generated. Throw expressions are parsed for semantic correctness, but then are treated as if they were a call to the function terminate. Use of this option causes the preprocessor macro _NO_EX_ to be defined.
Source files compiled with and without -noex may be linked together (provided -noex is not used when linking). Exceptions will pass through functions in source files compiled with -noex, but the destructors of automatic variables in those functions will not be called.
Turns off support of RTTI (run-time type information). This should save some space in the resulting executable. With this option, a typeid expression results in an exception being thrown, and a dynamic_cast expression always fails (by either returning 0 or throwing an exception) if the source type is polymorphic.
The scope of a variable declared in the initialization expression of a for statement was changed by the C++ standardization committee. When C++ was first invented, such variables were in the scope that contained the for statement. For example, according to the old language rules:
for ( int i = 0; ; ) { func(i); } func(i); // OK, "i" still defined for ( i = 0; ; ) { } // OK, "i" still defined for ( int i = 0; ; ) { } // Error, "i" redefined
The C++ committee changed the language so that a variable declared in the initialization expression of a for statement is in the scope of the for statement itself, not in the enclosing scope. For example, according to the new language rules:
for ( int i = 0; ; ) { func(i); } func(i); // Error, "i" undefined for ( i = 0; ; ) { } // Error, "i" undefined for ( int i = 0; ; ) { } // OK, defines new "i"
Apex C++ implements the new behavior by default. Using the -old_for option causes the compiler to use the old behavior. This may be necessary when compiling old code designed to take advantage of the old behavior.
Turns anachronism messages into errors, which will cause some programs that would have been accepted by the compiler to be rejected. Anachronism messages are usually used for constructs that used to be legal C++, but are now illegal. For a list of anachronisms, see Anachronistic constructs. In some future release of the compiler, anachronisms may be changed to errors, so use of this option is encouraged.
For each enumeration type, the compiler must pick an integral type to use as the underlying type for the enumeration type. In C, it always picks int and reports an error if any of the enumeration constants are outside the range of int. In C++ the compiler picks the smallest type that is equal to or larger than int that will hold all the enumeration constants in the given type.
The -shortenum option affects the underlying type used in C++, but not in C. In C, the underlying type is still always int. But in C++, the underlying type is the smallest integral type that will hold all the enumeration constants, regardless of whether or not this type is smaller than int. The option does not affect enumerated types defined within extern "C" blocks. For example, given:
enum A { a0, a1 }; enum B { b0, b1 = USHRT_MAX }; enum C { c0, c1 = UINT_MAX }; extern "C" { enum D { d0, d1 }; }
Without -shortenum, the underlying types of A, B, C, and D will be int, int, unsigned int, and int respectively. With -shortenum, they will be char, unsigned short, unsigned int, and int.
These options can be used to specify whether the type char is a signed or unsigned type. The option -signed causes char to be a signed type. The option -unsigned causes char to be an unsigned type. One of these is the default and therefore has no effect, and the other can be used to override the default. On Solaris, SunOS, HP-UX, Digital Unix, and all non-PowerPC embedded systems, the default is -signed. On AIX, IRIX, and all PowerPC embedded systems, the default is -unsigned. When one of these options is used to override the default, the macros CHAR_MIN and CHAR_MAX in limits.h are not affected and will therefore be incorrect. If char is a signed type, then the macro _SIGNEDCHAR_ will be automatically defined by the compiler.
C++ standard libraryApex C++ comes with two different C++ libraries. The old library is used by default, or is available with the -oldlib option. The new library is used with the -newlib option. In some future release of the compiler, the default may be changed from the old library to the new library, and -oldlib will be necessary to use the old version of the library.
Old C++ Library
This library is designed to be compatible with existing C++ code that is not meant to conform to the forthcoming C++ standard. It consists mostly of Rogue Wave Standard C++ Library 1.2.1 (which includes STL, a string class, complex numbers, and the exception class hierarchy), and a version of I/O streams modeled after the Cfront compiler.
This version of the library is not expected to change much in the future. It will be supported as long as there exists code that uses it, but it will probably not be expanded, and few new features will be added.
Many header files have two different versions, one with a .h extension, and one without (for example, vector.h and vector). By default, the two versions are identical. If the option -ns_std is used, then the version without the .h declares all its contents in the namespace std, while the version with the .h declares everything at global scope. The header files for I/O streams do not have versions without .h. If the .h version of the header file conflicts with a system include file, then it is renamed, putting cpp_ in front (for example, string and cpp_string.h). This is the case for limits, memory, and string.
algorithm, bitset, complex, deque, exception, functional, iterator, limits, list, map, memory, new, numeric, queue, set, stack, stdexcept, string, tree, utility, vector, and their .h versions:
These headers are part of Rogue Wave Standard C++ Library 1.2.1. Consult the Rogue Wave documentation for their contents. These headers are encrypted so that they may only be used with Apex C++. To view their contents, you must use the Apex debugger or Apex text editor.
I/O streams for files. Declares classes filebuf, ifstream, ofstream, and fstream.
Macros for faking generic class definitions. This header is obsolete and should not be used.
Macros for defining I/O stream manipulators.
Basic declarations for I/O streams. Declares classes ios, streambuf, istream, ostream, iostream, istream_withassign, ostream_withassign, and iostream_withassign. Declares the variables cin, cout, cerr, clog, endl, ends, flush, dec, hex, oct, and ws.
Implementation of I/O streams on top of C standard I/O files.This header file is obsolete. It declares the classes stdiobuf and stdiostream.
Implementation of I/O streams on top of character strings. Declares the classes strstreambuf, istrstream, ostrstream, and strstream.
Includes many of the other I/O stream header files. This header file is obsolete.
Definitions of class type_info, bad_cast, and bad_typeid, which are used to support RTTI.
New C++ Library
This version of the library, available with the option -newlib (which must be used both when compiling and when linking, that is, it must be part of both the CPP_OPTIONS and CPP_LINK_OPTIONS switches), is Rogue Wave Standard C++ Library 2.0. It is considered to be a pre-release, and therefore its use is not strongly encouraged. It was written to be as close as possible to the emerging C++ standard. This means it has many features not available in the old version of the C++ library, most notably locale, valarray, numeric_limits, and wchar_t versions of I/O streams. The library is limited by features that are not supported by the compiler, such as template member functions and partial specializations, and the library does not have the latest changes made by the standards committee. While it is expected that the implementation of the library may change significantly in future releases, its interface is not expected to change significantly, other than when the compiler adds support for template member functions and partial specializations. So code developed against this library will be more likely to work in the future, especially when ported to other standard C++ compilers.
For documentation of the library interface, see the accompanying Rogue Wave documentation.
According to the C++ standard, header file names do not have any extension, such as the .h extension used by the C standard header files. For example, iostream.h has become iostream. In order to support old code, versions of the header files with .h will continue to be supported. The version without .h will put all its declarations in the namespace std, as the C++ standard requires, while the version with .h will put its declarations in the global namespace. In three cases, string, limits, and memory, the version with .h would conflict with the names of other existing header files. So the .h version has cpp_ added at the beginning of the name, producing cpp_string.h, cpp_limits.h, cpp_limits.h.
This new library will break code that was designed for C++ libraries that came with older C++ compilers. The most likely problem areas are I/O streams. They are now template classes, even though the names istream, ostream, and their relatives will still work. Much code that uses I/O streams will still work without change, but other code will break. For example, it is no longer possible to simply have a forward declaration of the I/O streams classes, such as
class iostream;
Instead, the header file iosfwd must be included.
Due to the size and complexity of the header files, compiling with the library will be very slow. Because the library makes extensive use of templates, debugging support may be limited.Use of valarray in certain situations may cause the compiler to fail with an internal error.
Rational Software Corporation http://www.rational.com support@rational.com techpubs@rational.com Copyright © 1993-2002, Rational Software Corporation. All rights reserved. |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |