C++ Migration Guide

Chapter 4 Using Iostreams and Library Headers

This chapter explains the library and header file changes in C++ 5.0.

Iostreams

The C++ 4.2 compiler implements classic iostreams, which never had a formal definition. The implementation is compatible with the version released with Cfront (1990), with some bug fixes.

Standard C++ defines a new and expanded iostreams (standard iostreams). It is better defined, feature-rich, and supports writing internationalized code.

With the C++ 5.0 compiler in compatibility mode, you get classic iostreams, the same version supplied with the C++ 4.2 compiler. Any existing iostream code that works with the 4.2 compiler should work exactly the same way with the 5.0 compiler in compatibility mode.

In standard mode, you get standard iostreams by default. If you use the standard form of header names (without ".h"), you get the standard headers, with all declarations in namespace std.

Each of the standard headers is also provided in a form ending with ".h" that makes the header names available in the global namespace via using-declarations. These headers are a Sun extension, and code that depends on them might not be portable. These headers allow you to compile existing (simple) iostream code without having to change the code, even though standard iostreams are used instead of classic iostreams. For example, the following example compiles using standard iostream name streams.

 #include <iostream> int main() { std::cout << "Hello, world!" << std::endl; }

The following example, compiles with using classic iostream name forms.

 #include <iostream.h> int main() { cout << "Hello, world!" << endl; }

Not all classic iostream code is compatible with standard iostreams. If your classic iostream code does not compile, you must either modify your code, or use classic iostreams entirely.

To use classic iostreams in standard mode, use the compiler option library=iostream on the CC command line. When this option is used, a special directory is searched that contains the classic iostream header files, and the classic iostream runtime library is linked with your program. You must use this option on all compilations that make up your program as well as on the final link phase, or you will get inconsistent program results.


Note -

Mixing old and new forms of iostreams--including the standard input and output streams cin, cout, and cerr--in the same program can cause severe problems and is not recommended.


Task (Coroutine) Library

The coroutine library, accessed via the <task.h> header, is no longer supported. Compared to the coroutine library, Solaris threads are better integrated into the language development tools (particularly the debugger) and the operating system.

Rogue Wave Tools.h++

The Sun C++ 4.2 compiler was delivered with Rogue Wave Tools.h++ Version 7 as the default, and with Tools.h++ Version 6 for compatibility with earlier compiler releases.

The C++ 5.0 compiler does not provide Tools.h++ Version 6; it supplies Tools.h++ Version 7. Tools.h++ Version 7 is the default for the C++ 5.0 compiler in both compatibility mode and standard mode.

The Rogue Wave Tools.h++ version 7 library is built with classic iostreams. Therefore, when you include the Rogue Wave tools library in standard mode, you must also include libiostream. However, you must be careful to not use the old and new forms of iostreams--including the standard input and output streams cin, cout, and cerr--in the same program. Doing so can cause severe problems and is not recommended.

To use the Rogue Wave Tools.h libraries in standard mode, use the following compiler option:

To use the Rogue Wave Tools.h libraries in compatibility mode, use the following compiler option:

Refer to C++ User's Guide or the CC.1 man page for more information about accessing Tools.h++.

C Library Headers

In compatibility mode, you use the standard headers from C in exactly the same way as before. The headers are in the /usr/include directory, supplied with the version of Solaris you are using.

For clarification, the headers being discussed are the 17 headers defined by the ISO C standard (ISO 9899:1990) plus its later addendum (1994):


<assert.h> <ctype.h>  <errno.h>  <float.h>  <iso646.h> <limits.h> 
<locale.h> <math.h>   <setjmp.h> <signal.h> <stdarg.h> <stdio.h>
<stdlib.h> <string.h> <time.h>   <wchar.h>  <wctype.h>

The hundreds of other headers that reside in and below the /usr/include directory are not affected by this language change because they are not part of the C language standard.

The C++ standard has changed the definition of the standard C headers.

You can include and use any of these headers in a C++ program the same as in previous versions of Sun C++, but some restrictions apply.

The C++ standard requires that the names of types, objects, and functions in these headers appear in namespace std as well as in the global namespace. This in turn means that the versions of these headers supplied with Solaris (including Solaris 7) cannot be used directly. If you compile in standard mode, you must use the versions of these headers that are supplied with the C++ 5.0 compiler. If you use the wrong headers, your program can fail to compile or link.

Just one restriction applies: Use the standard spelling for the header, not a path name. For example, write:

#include <stdio.h> // Correct

and not either of these:

#include "/usr/include/stdio.h" // Wrong #include </usr/include/stdio.h> // Wrong

The C++ standard also introduces a second version of each of the 17 standard C headers. For each header of the form <NAME.h>, there is an additional header of the form <cNAME>. That is, the trailing ".h" is dropped, and a leading "c" is added. Some examples: <cstdio>, <cstring>, <cctype>.

These headers contain the names from the original form of the header, but appear only in namespace std. An example of use according to the C++ standard is:


#include <cstdio>
int main() { 		
    printf("Hello, ");       // Error, printf unknown
    std::printf("world!\n"); // OK
}

Because the code uses <cstdio> instead of <stdio.h>, the name printf appears only in namespace std and not in the global namespace. You must either qualify the name printf, or add a using-declaration:


#include <cstdio>
using std::printf;
int main() {
    printf("Hello, ");       // OK
    std::printf("world!\n"); // OK
}

The standard C headers in /usr/include contain many declarations that are not allowed by the C standard. The declarations are there for historical reasons, primarily because Unix systems have traditionally had the extra declarations in those headers, or because other standards (like POSIX or XOPEN) require them. For continued compatibility, these extra names continue to appear in the Sun C++ versions of the <NAME.h> headers, but only in the global namespace. These extra names do not appear in the <cNAME> versions of the headers. Since these new headers have never been used in any previous program, there is no compatibility or historical issue. Consequently, you might not find the <cNAME> headers to be useful for general programming. If you want to write maximally portable standard C++ code, however, be assured that the <cNAME> headers do not contain any unportable declarations. The following example uses <stdio.h>:


#include <stdio.h>                     // stdin in global namespace
int f() { return fileno(stdin); }      // OK
int g() { return std::fileno(stdin); } // Error


#include <cstdio>                           // stdin in namespace std
int f() { return fileno(std::stdin); }      // Error
int g() { return std::fileno(std::stdin); } // Error

The following example uses <cstdio>:

Function fileno is an extra function that for compatibility continues to appear in <stdio.h>, but only in the global namespace, not in namespace std. Because it is an extra function, it does not appear in <cstdio> at all.


Note -

The C++ 5.0 version of the C standard headers is not fully compliant in all these respects on Solaris 2.5.1 or 2.6.


The C++ standard allows using both the <NAME.h> and <cNAME> versions of the standard C headers in the same compilation unit. Although you probably would not do this on purpose, it can happen when you include, for example, <cstdlib> in your own code, and some project header you use includes <stdlib.h>. On Solaris environments 2.5.1 and 2.6, this mixing does not work for some headers, particularly for the <wchar.h>/<cwchar> and <wctype.h>/<cwctype> header pairs. If you get compiler complaints about one of these headers, use the <NAME.h> version of the header in your code instead of the <cNAME> version.

Standard Header Implementation

The C++ User's Guide explains in detail how standard headers are implemented along with the reasons for the implementation method. When you include any of the standard C or C++ headers, the compiler actually searches for a file with the specified name suffixed by ".SUNWCCh". For example, <string> causes a search for <string.SUNWCCh> and <string.h> causes a search for <string.h.SUNWCCh>. The compiler's include directory contains both spellings of the names, and each pair of spellings refers to the same file. For example, in directory include/CC you find both string and string.SUNWCCh. They refer to the same file, the one you get when you include <string>.

In error messages and debugger information, the suffix is suppressed. If you include <string>, error message and debugger references to that file mention string. File dependency information uses the name string.SUNWCCh to avoid problems with default makefile rules regarding unsuffixed names. If you want to search for just header files (using the SunOS find command, for example) you can look for the .SUNWCCh suffix.