C H A P T E R 4 |
Language Extensions |
The -features=extensions option enables you to compile nonstandard code that is commonly accepted by other C++ compilers. You can use this option when you must compile invalid code and you are not permitted to modify the code to make it valid.
This chapter describes the language extensions that the compiler supports when you use the -features=extensions options.
The C++ standard says that an overriding virtual function must not be less restrictive in the exceptions it allows than any function it overrides. It can have the same restrictions or be more restrictive. Note that the absence of an exception specification allows any exception.
Suppose, for example, that you call a function through a pointer to a base class. If the function has an exception specification, you can count on no other exceptions being thrown. If the overriding function has a less-restrictive specification, an unexpected exception could be thrown, which can result in bizarre program behavior followed by a program abort. This is the reason for the rule.
When you use -features=extensions, the compiler will allow overriding functions with less-restrictive exception specifications.
When you use -features=extensions, the compiler allows the forward declaration of enum types and variables. In addition, the compiler allows the declaration of a variable with an incomplete enum type. The compiler will always assume an incomplete enum type to have the same size and range as type int on the current platform.
The following two lines show an example of invalid code that will compile when you use the -features=extensions option.
enum E; // invalid: forward declaration of enum not allowed E e; // invalid: type E is incomplete |
Because enum definitions cannot reference one another, and no enum definition can cross-reference another type, the forward declaration of an enumeration type is never necessary. To make the code valid, you can always provide the full definition of the enum before it is used.
When you use -features=extensions, incomplete enum types are taken as forward declarations. For example, the following invalid code will compile when you use the -features=extensions option.
typedef enum E F; // invalid, E is incomplete |
As noted previously, you can always include the definition of an enum type before it is used.
Because an enum declaration does not introduce a scope, an enum name cannot be used as a scope qualifier. For example, the following code is invalid.
enum E { e1, e2, e3 }; int i = E::e1; // invalid: E is not a scope name |
To compile this invalid code, use the -features=extensions option. The -features=extensions option instructs the compiler to ignore a scope qualifier if it is the name of an enum type.
To make the code valid, remove the invalid qualifier E::.
Note - Use of this option increases the possibility of typographical errors yielding incorrect programs that compile without error messages. |
An anonymous struct declaration is a declaration that declares neither a tag for the struct, nor an object or typedef name. Anonymous structs are not allowed in C++.
The -features=extensions option allows the use of an anonymous struct declaration, but only as member of a union.
The following code is an example of an invalid anonymous struct declaration that will compile when you use the -features=extensions option.
union U { struct { int a; double b; }; // invalid: anonymous struct struct { char* c; unsigned d; }; // invalid: anonymous struct }; |
The names of the struct members are visible without qualification by a struct member name. Given the definition of U in this code example, you can write:
U u; u.a = 1; |
Anonymous structs are subject to the same limitations as anonymous unions.
Note that you can make the code valid by giving a name to each struct, such as:
union U { struct { int a; double b; } A; struct { char* c; unsigned d; } B; }; U u; U.A.a = 1; |
You are not allowed to take the address of a temporary variable. For example, the following code is invalid because it takes the address of a variable created by a constructor call. However, the compiler accepts this invalid code when you use the -features=extensions option.
class C { public: C(int); ... }; void f1(C*); int main() { f1( &C(2) ); // invalid } |
Note that you can make this code valid by using an explicit variable.
C c(2); f1(&c); |
The temporary object is destroyed when the function returns. Ensuring that the address of the temporary variable is not retained is the programmer's responsibility. In addition, the data that is stored in the temporary variable (for example, by f1) is lost when the temporary variable is destroyed.
The following code is invalid.
class A { friend static void foo(<args>); ... }; |
Because a class name has external linkage and all definitions must be identical, friend functions must also have external linkage. However, when you use the -features=extensions option, the compiler to accepts this code.
Presumably the programmer's intent with this invalid code was to provide a nonmember "helper" function in the implementation file for class A. You can get the same effect by making foo a static member function. You can make it private if you do not want clients to call the function.
When you use -features=extensions, the compiler implicitly declares the identifier __func__ in each function as a static array of const char. If the program uses the identifier, the compiler also provides the following definition where function-name is the unadorned name of the function. Class membership, namespaces, and overloading are not reflected in the name.
static const char __func__[] = "function-name"; |
For example, consider the following code fragment.
#include <stdio.h> void myfunc(void) { printf("%s\n", __func__); } |
Each time the function is called, it will print the following to the standard output stream.
Copyright © 2002, Sun Microsystems, Inc. All rights reserved.