United States    
COMPAQ STORE | PRODUCTS | SERVICES | SUPPORT
| CONTACT US | SEARCH
C++
Compaq C++

Compaq C++
Using Compaq C++ for Tru64 UNIX and Linux Alpha


Previous Contents Index


Chapter 7
The C++ Standard Library

The C++ Standard Library provided with this release defines a complete specification of the International C++ Standard, with some differences, as described in the Compaq C++ Release Notes for Tru64 UNIX .

The Standard Library in this release includes the ANSI locale and iostream libraries.

Portions of the ANSI C++ Standard Library have been implemented in Compaq C++ using source licensed from and copyrighted by Rogue Wave Software, Inc. Information pertaining to the C++ Standard Library has been edited and incorporated into Compaq C++ documentation with permission of Rogue Wave Software, Inc. All rights reserved.

On Tru64 UNIX, some of the components in the C++ Standard Library are designed to replace nonstandard components that are currently distributed in the Class Library. The Class Library will continue to be provided in its nonstandard form. However, you now have the option of using new standard components.

In this release, the shared libraries for the Complex and Task packages have been removed from the compiler kit. The redistribution kits that ship on the Tru64 Associated Products disribution have been removed from releases after Tru64 5.0A. Although applications can continue to use these libraries, they are linked statically. These libraries may be completely removed in a future release.

Compaq recommends that code using complex be migrated as documented in Section 7.5.4. Code using task should migrate to using Posix Threads (see man pthread ).

This chapter provides information about the implementation of the Standard Library, including upward compatibility, compiling, linking, and thread safety. Small example programs showing how to use the C++ standard library are located in the directory /usr/examples/cxx .

The following are Standard Library options:

-[no]using_std

Controls whether Standard Library header files are processed as though the compiled code were written as follows:


     using namespace std; 
     #include <header> 

These options are provided for compatibility for users who do not want to qualify use of each Standard Library name with std:: or put using namespace std; at the top of their sources.

-using_std turns implicit using namespace std on; this is the default when compiling -std arm , -std cfront , -std ms , or -std ansi .

-nousing_std turns implicit using namespace std off; this is the default when compiling -std strict_ansi or -std strict_ansi_errors .

-[no]stdnew

Controls whether calls are generated to the ANSI or pre-ANSI implementation of the operator new() . On memory allocation failure, the ANSI implementation throws std::bad_alloc , while the pre-ANSI implementation returns 0.

-stdnew generates calls to the ANSI new() implementation; this is the default when compiling -std ansi , -std strict_ansi and -std strict_ansi_errors .

-nostdnew generates calls to the pre-ANSI new() implementation; this is the default when compiling -std arm , -std cfront and -std ms .

-[no]global_array_new

Controls whether calls to global array new and delete are generated as specified by ANSI. Pre-ANSI global array new generated calls to operator new() . According to ANSI, use of global array new generate calls to operator new()[] .

-global_array_new generates calls to operator new()[] for global array new expressions such as new int[4] ; this is the default when compiling -std ansi , -std strict_ansi , -std strict_ansi_errors , and -std ms .

-noglobal_array_new generates calls to operator new() for global array new expressions such as new int[4] and preserves compatibility with Version 5.n; this is the default when compiling -std arm and -std cfront .

7.1 Important Compatibility Information

The following sections describe specific compatibility issues.

7.1.1 -[no]using_std Compiler Compatibility Switch

All Standard Library names in Compaq C++ are inside the namespace std . Typically you would qualify each Standard Library name with std:: or put using namespace std; at the top of your source file.

To make things easier for existing users, using namespace std; is included in a file provided with every Standard Library header when you are in arm , cfront , gnu , ms , or ansi compiler modes. This is not the default in strict_ansi or strict_ansi_errors mode.

The compiler supplied switches -nousing_std and -using_std can be used to override the default. -nousing_std turns the implicit using namespace std off; -using_std turns it on.

7.1.2 Pre-ANSI/ANSI Iostreams Compatibility

The C++ Standard Library offers support for the standard iostreams library based on the International C++ Standard. These standard iostream classes are in the new header files <iostream>, <ostream>, <istream> , and so on (no .h or .hxx extension).

For backward compatibility, the pre-ANSI iostream library is still provided in the old header files iostream.hxx , istream.hxx , and so on. The two libraries exhibit subtle differences and incompatibilities.

Users can choose which version (ANSI or pre-ANSI) of iostreams they want to use; either version of iostreams can be integrated seamlessly with the new Standard Library and string functionality.

To accomplish this goal, macros called __USE_STD_IOSTREAM and
__NO_USE_STD_IOSTREAM are provided. If you do not set these macros explicitly, the default in arm , cfront , gnu , ms , and ansi modes is to use the pre-ANSI iostream library. In strict_ansi and strict_ansi_errors mode, the default is to use the ANSI iostreams library.

You override the default by defining __USE_STD_IOSTREAM or
__NO_USE_STD_IOSTREAM on either the command line or in your source code.

In arm , cfront , ms , and ansi modes, specify use of the ANSI iostreams in one of the following ways:

In strict_ansi and strict_ansi_errors modes specify use of the pre-ANSI iostreams in one of the following ways:

A #error warning appears:

  1. If you have explicitly included the wrong header for the current mode. For example, if you say #include <iostream> (an ANSI header) and you are in -std ansi , -std cfront , gnu , -std ms or -std arm mode, and if you have not entered -D__USE_STD_IOSTREAM on the command line, an error message appears.
  2. If you are in -std strict_ansi or -std strict_ansi_errors , and you enter #include <iostream.h> , an error message appears unless you also enter -D__NO_USE_STD_IOSTREAM .

Many of the other headers, <string> for example, make use of the iostream classes. The default version of iostreams that is automatically included when you include one of these headers depends on the mode you compile in and the setting of the macros __USE_STD_IOSTREAM and __NO_USE_STD_IOSTREAM as described earlier.

Because the standard locale class and the standard iostream class are so closely tied, you cannot use the standard locale class with the pre-standard iostream classes. If you want to use locale, you must use the standard iostream classes.

It is possible to use the pre-ANSI and the ANSI iostream library in the same source file, because all the standard iostream names (that is, cout , cin , and so on) are in namespace std , and all the pre-ANSI names are in the global namespace. This is not recommended, though, because there is no guarantee of stream objects being the same size or, for example, of ::cout being in sync with std::cout .

To do this in all modes, include a pre-ANSI iostreams header before an ANSI iostreams header as follows:


  #include <stdlib.h> 
  #undef __USE_STD_IOSTREAM 
  #include <iostream.h> 
  #define __USE_STD_IOSTREAM 
  #include <iostream> 
 
  int main() 
  { 
    std::string s("abc"); 
    ::cout << "abc" << endl;         // pre-standard iostreams 
    std::cout << "abc" << std::endl; // standard iostreams 
    return EXIT_SUCCESS; 
  } 

To do this in all modes, if you include an ANSI iostreams header before a pre-ANSI iostreams header, follow these steps:

  1. Compile your source using -nousing_std .
  2. Use the __USE_STD_IOSTREAM macro as shown in the following example. You must define __USE_STD_IOSTREAM at the end of your include file list so that the template definition files (the .cc files) are included in the correct mode.


      // Compile this with -nousing_std 
      #include <stdlib.h> 
      #define __USE_STD_IOSTREAM 
      #include <iostream> 
      #undef __USE_STD_IOSTREAM 
      #include <iostream.h> 
      #define __USE_STD_IOSTREAM // so the template definition files are ok 
     
      int main() 
      { 
        std::string s("abc"); 
        ::cout << "abc" << endl; // pre-standard iostreams 
        std::cout << "abc" << std::endl; // standard iostreams 
        return EXIT_SUCCESS; 
      } 
    

7.1.3 Support for pre-ANSI and ANSI operator new()

The Standard C++ Library supports the ANSI implementation of the operator new() as well as the pre-ANSI implementation of operator new() . The ANSI implementation throws std::bad_alloc on memory allocation failures.

The pre-ANSI implementation of the operator new() returns 0 on memory allocation failures. Because the ANSI behavior is incompatible with pre-ANSI applications, a compile time switch has been added ( -[no]stdnew ) to control whether calls to ANSI new() or pre-ANSI new are generated.

The following examples show how ANSI versus pre-ANSI new() check for memory allocation. First, here is an ANSI new() check for memory allocation failure:


            try { 
                myobjptr = new (myobj); 
            } 
            catch (std::bad_alloc e) { 
                cout << e.what() << endl; 
            }; 

The following example shows a pre-ANSI new() check for memory allocation failure:


            if ((myobjptr = new (myobj)) == 0) 
                call_failure_routine(); 

When upgrading pre-ANSI new() code to work with the C++ Standard Library you also can use the nothrow version of ANSI new() . To do so in the pre-ANSI example, you could recode it as follows:


            if ((myobjptr = new (myobj, nothrow)) == 0) 
                 call_failure_routine(); 

Two command line switches are available in the compiler to control whether calls are generated to the ANSI or pre-ANSI implementation of operator new() . Use the -stdnew switch to generate calls to the ANSI new() implementation. Use the -nostdnew switch to generate calls to the pre-ANSI new() implementation.

You can override global new() by declaring your own functions.

When compiling with -std ansi , -std strict_ansi , and -std strict_ansi_errors , -stdnew is the default. When compiling with -std arm , -std cfront , gnu , and -std ms , -nostdnew is the default. The compiler defines the macro __STDNEW when the -stdnew option is specified.

7.1.4 Overriding operator new()

If you want to define a global operator new() to displace the version used by the C++ Standard Library or C++ Class Library, follow these steps:

  1. Define a module that will contain two entry points for your version of global operator new() : one for the Standard Library and one for the Class Library.
    When you link with this module, your version of the global operator new() displaces the version used by either the C++ Standard Library or C++ Class Library.
  2. Decide whether you want to compile the module using the -stdnew or the -nostdnew option. You must always use the same option when compiling the module.
  3. Code the module for the compilation method you have chosen, as follows:

    For module to be compiled with -stdnew

    1. Include two entry points for your version of global operator new() :
      • __7__nw__FUl ( -model ansi ) or __nw__XUl ( -model arm ), which is used to override global operator new() in the Class Library. This entry point has the name generated by the Class Library version of global
        operator new() , which is the mangled name used in the Class Library.
      • new , which is used to override global operator new() in the Standard Library. This entry point has the name generated by the Standard Library version of global operator new() .
    2. Define global operator new() in terms of the entry point new . The __7__nw__FUl ( -model ansi ) or __nw__XUl ( -model arm ) version is declared with extern C and simply calls the first version. Your module will contain two routines similar to the following:


           #include <new> 
           ... 
       
           // Redefine global operator new(), 
           // entry point into C++ Standard Library. 
           // Also override user calls to operator new() 
       
           void *operator new(size_t size) throw(std::bad_alloc) { 
           printf("in my global new\n"); 
           ... 
           } 
       
           // Entry point into C++ Class Library 
       
           #ifdef __MODEL_ANSI 
           extern "C" void *__7__nw__FUl(size_t size) { 
           #else  //__MODEL_ARM 
           extern "C" void *__nw__XUl(size_t size) { 
           #endif 
                return ::operator new(size); 
           } 
      

    For module to be compiled with -nostdnew

    1. Include two entry points for your version of global operator new() :
      • __7__stdnw__FUl ( -model ansi ) or __stdnw__XUl ( -model arm ), which is used to override global operator new() in the Standard Library. This entry point has the name generated by the Standard Library version of global operator new() , which is the mangled name used in the Standard Library.
      • new , which is used to override global operator new() in the Class Library. This entry point has the name generated by the Class Library version of global operator new() .
    2. Define global operator new in terms of the entry point new . The __7__stdnw__FUl ( -model ansi ) or __stdnw__XUl ( -model arm ) version is declared with extern C and simply calls the first version. Your module will contain two routines similar to the following:


           #include <new> 
           ... 
       
           // Redefine global operator new(), 
           // entry point into C++ Class Library. 
           // Also override user calls to operator new(). 
       
           void *operator new(size_t size) { 
           printf("in my global new\n"); 
           ... 
           } 
       
           // Entry point into C++ Standard Library 
       
           #ifdef __MODEL_ANSI 
           extern "C" void *__7__stdnw__FUl(size_t size) { 
           #else  //__MODEL_ARM 
           extern "C" void *__stdnw__XUl(size_t size) { 
           #endif 
                return ::operator new(size); 
           } 
      

7.1.5 Support for Global array new and delete Operators

Compaq C++ Version 6.n fully supports the array new and delete operators as described in the ANSI standard. Previous versions did not. You might therefore encounter a compatibility problem if you have overridden the run-time library's operator new() with your own version.

For example:


#include <stdlib.h> 
#include <iostream.h> 
 
inline void* operator new(size_t s) { 
 cout << "called my operator new" << endl; 
 return 0; 
} 
 
int main() { 
 new int;    // ok, this still calls your own 
 new int[4]; // In V6.0 calls the C++ library's operator new[] 
        return EXIT_SUCCESS; 
} 

In older versions, both new int and new int[4] would generate a call to operator new() (they would just be asking for different sizes). With the current compiler, new int still generates a call to operator new() . However, new int[4] generates a call to operator new()[] . This means that if you still want to override the library's operator new you must do one of the following:

  1. Provide your own definition of operator new()[] .
  2. Use the -noglobal_array_new switch.

The -noglobal_array_new switch converts all expressions such as new int[4] to calls to the global operator new() , thus preserving compatibility with older compiler versions.

This switch has no effect on class-specific array operator new and delete ; it affects only the global operators.

When compiling with -std ansi , -std strict_ansi , -std strict_ansi_errors , and -std ms modes , -global_array_new is the default. When compiling with -std arm or -std cfront modes, -noglobal_array_new is the default. A macro __GLOBAL_ARRAY_NEW is predefined by the compiler when -global_array_new is used.

7.2 How to Build Programs Using the C++ Standard Library

When you use the cxx command to compile and link programs that use the C++ Standard Library, no special switches are required. The Compaq C++ driver automatically includes the Standard Library run-time support ( -lcxxstd ) on the link command, and automatic template instantiation ( -pt ) is the default mode.

For example, to build a program called prog.cxx that uses the Standard Library, you can simply use the following command:


cxx prog.cxx 

[Tru64] Thread Safety

The Standard Library provided with this release is thread safe but not thread reentrant. Thread safe means that all library internal and global data is protected from simultaneous access by multiple threads. In this way, internal buffers as well as global data like cin and cout are protected during each individual library operation. Users, however, are responsible for protecting their own objects.

According to the C++ standard, results of recursive initialization are undefined. To guarantee thread safety, the compiler inserts code to implement a spinlock if another thread is initializing local static data. If recursive initialization occurs, the code deadlocks even if threads are not used.

[Linux] Thread Safety

The Standard Library provided with Compaq C++ for Linux Alpha is not thread safe.

7.3 Optional Switch to Control Buffering

The inplace_merge , stable_sort , and stable_partition algorithms require the use of a temporary buffer. Two methods are available for allocating this buffer:

By default, the current library makes use of the preallocated buffer, which avoids the overhead of run-time allocation. If your application requires a buffer that exceeds 16K, it can not take advantage of this default.

If you are concerned with minimizing the use of stack space in your program, or if your application requires a buffer that exceeds 16K, define the __DEC_DYN_ALLOC macro to enable dynamic buffering. Do this by adding the following to your compile command line:


-D__DEC_DYN_ALLOC 

7.4 Enhanced Compile-time Performance of ANSI Iostreams

To speed up the compile-time performance of programs that use the standard iostream and locale components, many common template instantiations of these components have been included in the Standard Library.

To force programs to create instantiations at compile-time (for example, if you want to debug them and thus need them to be compiled with the -gall option ), define the macro __FORCE_INSTANTIATIONS on the command line. This definition suppresses the #pragma do_not_instantiate directives in the headers so that the compiler creates the instantiations in your repository directory.

You must then specify the -nopreinst option to force the compiler to link your instantiations instead of those in the Standard Library.

7.5 Upgrading from the Class Library to the Version 6.n Standard Library

The following discussion guides you through upgrading the Class Library code to use the Standard Library, specifically replacing the vector and stack classes in the vector.hxx header file to the Standard Library vector and stack classes.

7.5.1 Upgrading from the Class Library Vector to the Standard Library Vector

To change your code from using the Class Library vector to the Standard Library vector, consider the following actions:

7.5.2 Upgrading from the Class Library Stack to the Standard Library Stack

To change your code from using the existing stack to the Standard Library stack, consider the following actions:

7.5.3 Upgrading from the Class Library String Package Code

The Standard Library basic_string can replace the Class Library String Package.

The following list guides you through upgrading nonstandard code to use the Standard Library basic_string :

7.5.4 Upgrading from the Class Library Complex to the ANSI Complex Class

This section explains how to upgrade from the pre-ANSI complex library to the current standard complex library.

In the pre-ANSI library, complex objects are not templatized. In the ANSI library, complex objects are templatized on the type of the real and imaginary parts. The pre-ANSI library assumes the type is double, whereas the ANSI library provides specializations for float, double, and long double as well as allowing users to specialize on their own floating point types.

Mathematical error checking is not supported in the ANSI library. Users who rely on detection of underflow, overflow, and divide by zero should continue using the pre-ANSI complex library.

The following is a detailed list of important changes:

7.5.5 Upgrading from the Pre-ANSI iostream library to the Standard Library

This section explains how to upgrade from the pre-ANSI iostream library to the ANSI iostream library. In this section, pre-ANSI iostream refers to versions of the iostream library found in the Class Library; ANSI iostream refers to versions found in the Standard Library.

There are a number of differences between the pre-ANSI and ANSI iostream library. One major difference between the pre-ANSI and ANSI iostream library is that the ANSI library is templatized on the object input/output on which operations are being performed. In the pre-ANSI library, iostreams has no templates. The ANSI library also provides specializations for char and wchar_t .

Important differences are as follows:


Previous Next Contents Index
  

1.800.AT.COMPAQ

privacy and legal statement