Libraries provide a way to share code among several applications and a way to reduce the complexity of very large applications. The C++ compiler gives you access to a variety of libraries. This chapter explains how to use these libraries.
The Solaris operating system comes with several libraries installed in /usr/lib. Most of these libraries have a C interface. Of these, the libc and libm, libraries are linked by the CC driver by default. The library libthread is linked if you use the–mt option. To link any other system library, use the appropriate –l option at link time. For example, to link the libdemangle library, pass –ldemangle on the CC command line at link time:
example% CC text.c -ldemangle |
The C++ compiler has its own runtime support libraries. All C++ applications are linked to these libraries by the CC driver. The C++ compiler also comes with several other useful libraries, as explained in the following section.
Several libraries are shipped with the C++ compiler. Some of these libraries are available only in compatibility mode (-compat=4), some are available only in the standard mode (–compat=5), and some are available in both modes. The libgc and libdemangle libraries have a C interface and can be linked to an application in either mode.
The following table lists the libraries that are shipped with the C++ compiler and the modes in which they are available.
Table 12–1 Libraries Shipped With the C++ Compiler
Library |
Description |
Available Modes |
---|---|---|
libstlport |
STLport implementation of the standard library. |
–compat=5 |
libstlport_dbg |
STLport library for debug mode |
–compat=5 |
C++ runtime |
–compat=5 |
|
C++ standard library |
–compat=5 |
|
Classic iostreams |
–compat=5 |
|
C++ runtime, classic iostreams |
–compat=4 |
|
Supports the -xia option |
–compat=5 |
|
complex library |
–compat=4 |
|
librwtool |
Tools.h++ 7 |
–compat=4,– compat=5 |
Debug-enabled Tools.h++ 7 |
–compat=4,–compat=5 |
|
Garbage collection |
C interface |
|
Demangling |
C interface |
Do not redefine or modify any of the configuration macros for STLport, Rogue Wave or Sun Microsystems C++ libraries. The libraries are configured and built in a way that works with the C++ compiler. libCstd and Tool.h++ are configured to inter-operate so modifying the configuration macros results in programs that will not compile, will not link, or do not run properly.
A brief description of each of these libraries follows.
libCrun: This library contains the runtime support needed by the compiler in the standard mode (–compat=5). It provides support for new/delete, exceptions, and RTTI.
libCstd: This is the C++ standard library. In particular, it includes iostreams. If you have existing sources that use the classic iostreams and you want to make use of the standard iostreams, you have to modify your sources to conform to the new interface. See the C++ Standard Library Reference online manual for details. You can access this manual by pointing your web browser to:
file:/opt/SUNWspro/docs/index.html |
If your compiler software is not installed in the /opt directory, ask your system administrator for the equivalent path on your system.
libiostream: This is the classic iostreams library built with– compat=5. If you have existing sources that use the classic iostreams and you want to compile these sources with the standard mode (–compat=5), you can use libiostream without modifying your sources. Use– library=iostream to get this library.
Much of the standard library depends on using standard iostreams. Using classic iostreams in the same program can cause problems.
libC: This is the library needed in compatibility mode (–compat=4). It contains the C++ runtime support as well as the classic iostreams.
libcomplex: This library provides complex arithmetic in compatibility mode (-compat=4). In the standard mode, the complex arithmetic functionality is available in libCstd.
libstlport: This is the STLport implementation of the C++ standard library. You can use this library instead of the default libCstd by specifying the option -library=stlport4. However, you cannot use libstlport and libCstd in the same program. You must compile and link everything, including imported libraries, using one or the other exclusively.
librwtool (Tools.h++): Tools.h++ is a C++ foundation class library from RogueWave. Version 7 of this library is provided with this release. This library is available in classic-iostreams form (-library=rwtools7) and standard-iostreams form (-library=rwtools7_std). For further information about this library, see the following online documentation.
Tools.h++ User’s Guide (Version 7)
Tools.h++ Class Library Reference (Version 7)
You can access this documentation by pointing your web browser to:
file:/opt/SUNWspro/docs/index.html |
If your compiler software is not installed in the /opt directory, ask your system administrator for the equivalent path on your system.
libgc: This library is used in deployment mode or garbage collection mode. Simply linking with the libgc library automatically and permanently fixes a program’s memory leaks. When you link your program with the libgc library, you can program without calling free or delete while otherwise programming normally. The garbage collection library has a dependency on the dynamic load library so specify -lgc and -ldl when you link your program.
Additional information can be found in the gcFixPrematureFrees(3) and gcInitialize(3) man pages.
libdemangle: This library is used for demangling C++ mangled names.
The man pages associated with the libraries described in this section are located in:
/opt/SUNWspro/man/man1
/opt/SUNWspro/man/man3
/opt/SUNWspro/man/man3C++
/opt/SUNWspro/man/man3cc4
If your compiler software is not installed in the /opt directory, ask your system administrator for the equivalent path on your system.
To access these man pages, ensure that your MANPATH includes /opt/SUNWspro/man (or the equivalent path on your system for the compiler software).
To access man pages for the C++ libraries, type:
example% man library-name |
To access man pages for version 4.2 of the C++ libraries, type:
example% man -s 3CC4 library-name |
You can also access the man pages by pointing your browser to:
file:/opt/SUNWspro/docs/index.html |
Some of the C++ libraries are linked by default by the CC driver, while others need to be linked explicitly. In the standard mode, the following libraries are linked by default by the CC driver:
In compatibility mode (-compat), the following libraries are linked by default:
-lC -lm -lc
See A.2.49 -library=l[,l...] for more information.
The CC driver provides several options to help you use libraries.
Use the– L option to specify a directory to be searched for the library.
Use the -mt option compile and link multithreaded code.
Use the -xia option to link the interval arithmetic libraries.
Use the -xlang option to link Fortran runtime libraries.
Use the– library option to specify the following libraries that are shipped with the Sun C++ compiler:
libCrun
libCstd
libiostream
libC
libcomplex
libstlport, libstlport_dbg
librwtool, librwtool_dbg
libgc
To use the classic-iostreams form of librwtool, use the -library=rwtools7 option. To use the standard-iostreams form of librwtool, use the -library=rwtools7_std option.
A library that is specified using both –library and –staticlib options will be linked statically. Some examples:
The following command links the classic-iostreams form of Tools.h++ version 7 and libiostream libraries dynamically.
example% CC test.cc -library=rwtools7,iostream |
The following command links the libgc library statically.
example% CC test.cc -library=gc -staticlib=gc |
The following command compiles test.cc in compatibility mode and links libC statically. Because libC is linked by default in compatibility mode, you are not required to specify this library using the– library option.
example% CC test.cc -compat=4 -staticlib=libC |
The following command excludes the libraries libCrun and libCstd, which would otherwise be included by default.
example% CC test.cc -library=no%Crun,no%Cstd |
By default, CC links various sets of system libraries depending on the command line options. If you specify -xnolib (or -nolib), CC links only those libraries that are specified explicitly with the -l option on the command line. (When -xnolib or -nolib is used, the -library option is ignored, if present.)
The –R option allows you to build dynamic library search paths into the executable file. At execution time, the runtime linker searches these paths for the shared libraries needed by the application. The CC driver passes– R/opt/SUNWspro/lib to ld by default (if the compiler is installed in the standard location). You can use -norunpath to disable building the default path for shared libraries into the executable.
Generally, two steps are involved in using a class library:
Include the appropriate header in your source code.
Link your program with the object library.
The C++ compiler provides two implementations of iostreams:
Classic iostreams. This term refers to the iostreams library shipped with the C++ 4.0, 4.0.1, 4.1, and 4.2 compilers, and earlier with the cfront-based 3.0.1 compiler. There is no standard for this library, but a lot of existing code uses it. This library is part of libC in compatibility mode and is also available in libiostream in the standard mode.
Standard iostreams. This is part of the C++ standard library, libCstd, and is available only in standard mode. It is neither binary-, nor source-compatible with the classic iostreams library.
If you have existing C++ sources, your code might look like the following example, which uses classic iostreams.
// file prog1.cc #include <iostream.h> int main() { cout << "Hello, world!" << endl; return 0; } |
The following command compiles in compatibility mode and links prog1.cc into an executable program called prog1. The classic iostream library is part of libC, which is linked by default in compatibility mode.
example% CC -compat prog1.cc -o prog1 |
The next example uses standard iostreams.
// file prog2.cc #include <iostream> int main() { std::cout << "Hello, world!" << std::endl; return 0; } |
The following command compiles and links prog2.cc into an executable program called prog2. The program is compiled in standard mode and libCstd, which includes the standard iostream library, is linked by default.
example% CC prog2.cc -o prog2 |
For more information about libCstd, see Caveats:. For more information about libiostream, see 13.3.1 Redistribution and Supported STLport Libraries.
For a full discussion of compilation modes, see the C++ Migration Guide.
The standard library provides a templatized complex library that is similar to the complex library provided with the C++ 4.2 compiler. If you compile in standard mode, you must use <complex> instead of <complex.h>. You cannot use <complex> in compatibility mode.
In compatibility mode, you must explicitly ask for the complex library when linking. In standard mode, the complex library is included in libCstd, and is linked by default.
There is no complex.h header for standard mode. In C++ 4.2, “complex” is the name of a class, but in standard C++, “complex” is the name of a template. It is not possible to provide typedefs that allow old code to work unchanged. Therefore, code written for 4.2 that uses complex numbers will need some straightforward editing to work with the standard library. For example, the following code was written for 4.2 and will compile in compatibility mode.
// file ex1.cc (compatibility mode) #include <iostream.h> #include <complex.h> int main() { complex x(3,3), y(4,4); complex z = x * y; cout << "x=" << x << ", y=" << y << ", z=" << z << endl; } |
The following example compiles and links ex1.cc in compatibility mode, and then executes the program.
example% CC -compat ex1.cc -library=complex example% a.out x=(3, 3), y=(4, 4), z=(0, 24) |
Here is ex1.cc rewritten as ex2.cc to compile in standard mode:
// file ex2.cc (ex1.cc rewritten for standard mode) #include <iostream> #include <complex> using std::complex; int main() { complex<double> x(3,3), y(4,4); complex<double> z = x * y; std::cout << "x=" << x << ", y=" << y << ", z=" << z << std::endl; } |
The following example compiles and links the rewritten ex2.cc in standard mode, and then executes the program.
% CC ex2.cc % a.out x=(3,3), y=(4,4), z=(0,24) |
For more information about using the complex arithmetic library, see Table 14–4.
The following table shows the compiler options for linking the C++ libraries. See A.2.49 -library=l[,l...] for more information.
Table 12–2 Compiler Options for Linking C++ Libraries
Library |
Compilation Mode |
Option |
---|---|---|
–compat=5 |
None needed -library=iostream |
|
complex |
–compat=4 -compat=5 |
-library=complex None needed |
–compat=4 –compat=5 |
-library=rwtools7 -library=rwtools7_std |
|
Tools.h++ version 7 debug |
–compat=4 –compat=5 |
-library=rwtools7_dbg -library=rwtools7_dbg,iostream -library=rwtools7_std_dbg |
–compat=4 –compat=5 |
-library=gc -library=gc |
|
STLport version 4 |
–compat=5 |
-library=stlport4 |
STLport version 4 debug |
–compat=5 |
-library=stlport4_dbg |
The CC driver links in shared versions of several libraries by default, including libc and libm, by passing a -llib option for each of the default libraries to the linker. (See 12.2.3 Default C++ Libraries for the list of default libraries for compatibility mode and standard mode.)
If you want any of these default libraries to be linked statically, you can use the -library option along with the –staticlib option to link a C++ library statically. This alternative is much easier than the one described earlier. For example:
example% CC test.c -staticlib=Crun |
In this example, the -library option is not explicitly included in the command. In this case the -library option is not necessary because the default setting for -library is Cstd,Crun in standard mode (the default mode).
Alternately, you can use the -xnolib compiler option. With the -xnolib option, the driver does not pass any -l options to ld; you must pass these options yourself. The following example shows how you would link statically with libCrun, and dynamically with libm, and libc in the Solaris 8, or Solaris 9 operating systems:
example% CC test.c– xnolib– lCstd– Bstatic– lCrun– Bdynamic– lm– lc |
The order of the -l options is important. The– lCstd,– lCrun, and -lm options appear before -lc.
Some CC options link to other libraries. These library links are also suppressed by -xnolib. For example, using the -mt option causes the CC driver to pass -lthread to ld. However, if you use both–mt and –xnolib, the CC driver does not pass-lthread to ld. See A.2.149 –xnolib for more information. See Linker and Libraries Guide for more information about ld.
The following shared libraries are included with the C++ compiler:
libCrun.so
libC.so
libcomplex.so
libstlport.so
librwtool.so
libgc.so
libgc_dbg.so
libCstd.so
libiostream.so
The occurrence of each shared object linked with the program is recorded in the resulting executable (a.out file); this information is used by ld.so to perform dynamic link editing at runtime. Because the work of incorporating the library code into an address space is deferred, the runtime behavior of the program using a shared library is sensitive to an environment change—that is, moving a library from one directory to another. For example, if your program is linked with libcomplex.so.5 in /opt/SUNWspro/lib, and the libcomplex.so.5 library is later moved into /opt2/SUNWspro/lib, the following message is displayed when you run the binary code:
ld.so: libcomplex.so.5: not found |
You can still run the old binary code without recompiling it by setting the environment variable LD_LIBRARY_PATH to the new library directory.
In a C shell:
example% setenv LD_LIBRARY_PATH \ /opt2/SUNWspro/release/lib:${LD_LIBRARY_PATH} |
In a Bourne shell:
example$ LD_LIBRARY_PATH=\ /opt2/SUNWspro/release/lib:${LD_LIBRARY_PATH} example$ export LD_LIBRARY_PATH |
release is specific for each release of the compiler software.
The LD_LIBRARY_PATH has a list of directories, usually separated by colons. When you run a C++ program, the dynamic loader searches the directories in LD_LIBRARY_PATH before it searches the default directories.
Use the ldd command as shown in the following example to see which libraries are linked dynamically in your executable:
example% ldd a.out |
This step should rarely be necessary, because the shared libraries are seldom moved.
When shared libraries are opened with dlopen, RTLD_GLOBAL must be used for exceptions to work.
See Linker and Libraries Guide for more information on using shared libraries.
Replacing the standard library that is distributed with the compiler is risky, and good results are not guaranteed. The basic operation is to disable the standard headers and library supplied with the compiler, and to specify the directories where the new header files and library are found, as well as the name of the library itself.
The compiler supports the STLport implementation of the standard library. See 13.3 STLport for more information.
You can replace most of the standard library and its associated headers. The replaced library is libCstd, and the associated headers are listed in the following table:
<algorithm> <bitset> <complex> <deque> <fstream <functional> <iomanip> <ios> <iosfwd> <iostream> <istream> <iterator> <limits> <list> <locale> <map> <memory> <numeric> <ostream> <queue> <set> <sstream> <stack> <stdexcept> <streambuf> <string> <strstream> <utility> <valarray> <vector> |
The replaceable part of the library consists of what is loosely known as “STL”, plus the string classes, the iostream classes, and their helper classes. Because these classes and headers are interdependent, replacing just a portion of them is unlikely to work. You should replace all of the headers and all of libCstd if you replace any part.
The standard headers <exception>, <new>, and <typeinfo> are tied tightly to the compiler itself and to libCrun, and cannot reliably be replaced. The library libCrun contains many “helper” functions that the compiler depends on, and cannot be replaced.
The 17 standard headers inherited from C (<stdlib.h>, <stdio.h>, <string.h>, and so forth) are tied tightly to the Solaris operating system and the basic Solaris runtime library libc, and cannot reliably be replaced. The C++ versions of those headers (<cstdlib>, <cstdio>, <cstring>, and so forth) are tied tightly to the basic C versions and cannot reliably be replaced.
To install the replacement library, you must first decide on the locations for the replacement headers and on the replacement for libCstd. For purposes of discussion, assume the headers are placed in /opt/mycstd/include and the library is placed in /opt/mycstd/lib. Assume the library is called libmyCstd.a. (It is often convenient if the library name starts with “lib”.)
On each compilation, use the -I option to point to the location where the headers are installed. In addition, use the -library=no%Cstd option to prevent finding the compiler’s own versions of the libCstd headers. For example:
example% CC -I/opt/mycstd/include -library=no%Cstd... (compile) |
During compiling, the -library=no%Cstd option prevents searching the directory where the compiler’s own version of these headers is located.
On each program or library link, use the -library=no%Cstd option to prevent finding the compiler’s own libCstd, the -L option to point to the directory where the replacement library is, and the -l option to specify the replacement library. Example:
example% CC -library=no%Cstd -L/opt/mycstd/lib -lmyCstd... (link) |
Alternatively, you can use the full path name of the library directly, and omit using the -L and -l options. For example:
example% CC -library=no%Cstd /opt/mycstd/lib/libmyCstd.a... (link) |
During linking, the -library=no%Cstd option prevents linking the compiler’s own version of libCstd.
C has 17 standard headers (<stdio.h>, <string.h>, <stdlib.h>, and others). These headers are delivered as part of the Solaris operating system, in the directory /usr/include. C++ has those same headers, with the added requirement that the various declared names appear in both the global namespace and in namespace std. On versions of the Solaris operating system prior to version 8, the C++ compiler supplies its own versions of these headers instead of replacing those in the /usr/include directory.
C++ also has a second version of each of the C standard headers (<cstdio>, <cstring>, and <cstdlib>, and others) with the various declared names appearing only in namespace std. Finally, C++ adds 32 of its own standard headers (<string>, <utility>, <iostream>, and others).
The obvious implementation of the standard headers would use the name found in C++ source code as the name of a text file to be included. For example, the standard headers <string> (or <string.h>) would refer to a file named string (or string.h) in some directory. That obvious implementation has the following drawbacks:
You cannot search for just header files or create a makefile rule for the header files if they do not have file name suffixes.
If you have a directory or executable program named string, it might erroneously be found instead of the standard header file.
On versions of the Solaris operating system prior to the Solaris 8 operating system, the default dependencies for makefiles when .KEEP_STATE is enabled can result in attempts to replace standard headers with an executable program. (A file without a suffix is assumed by default to be a program to be built.)
To solve these problems, the compiler include directory contains a file with the same name as the header, along with a symbolic link to it that has the unique suffix .SUNWCCh (SUNW is the prefix for all compiler-related packages, CC is the C++ compiler, and h is the usual suffix for header files). When you specify <string>, the compiler rewrites it to <string.SUNWCCh> and searches for that name. The suffixed name will be found only in the compiler’s own include directory. If the file so found is a symbolic link (which it normally is), the compiler dereferences the link exactly once and uses the result (string in this case) as the file name for error messages and debugger references. The compiler uses the suffixed name when emitting file dependency information.
The name rewriting occurs only for the two forms of the 17 standard C headers and the 32 standard C++ headers, only when they appear in angle brackets and without any path specified. If you use quotes instead of angle brackets, specify any path components, or specify some other header, no rewriting occurs.
The following table illustrates common situations.
Table 12–3 Header Search Examples
Source Code |
Compiler Searches For |
Comments |
---|---|---|
<string> |
string.SUNWCCh |
C++ string templates |
<cstring> |
cstring.SUNWCCh |
C++ version of C string.h |
<string.h> |
string.h.SUNWCCh |
C string.h |
<fcntl.h> |
fcntl.h |
Not a standard C or C++ header |
"string" |
string |
Double-quotation marks, not angle brackets |
<../string> |
../string |
Path specified |
If the compiler does not find header.SUNWCCh, the compiler restarts the search looking for the name as provided in the #include directive. For example, given the directive #include <string>, the compiler attempts to find a file named string.SUNWCCh. If that search fails, the compiler looks for a file named string.
Because of the search algorithm described in 12.7.5 Standard Header Implementation, you do not need to supply SUNWCCh versions of the replacement headers described in 12.7.3 Installing the Replacement Library. But you might run into some of the described problems. If so, the recommended solution is to add symbolic links having the suffix .SUNWCCh for each of the unsuffixed headers. That is, for file utility, you would run the command
example% ln -s utility utility.SUNWCCh |
When the compiler looks first for utility.SUNWCCh, it will find it, and not be confused by any other file or directory called utility.
Replacing the standard C headers is not supported. If you nevertheless wish to provide your own versions of standard headers, the recommended procedure is as follows:
Put all the replacement headers in one directory.
Create a .SUNWCCh symbolic link to each of the replacement headers in that directory.
Cause the directory that contains the replacement headers to be searched by using the -I directives on each invocation of the compiler.
For example, suppose you have replacements for <stdio.h> and <cstdio>. Put the files stdio.h and cstdio in directory /myproject/myhdr. In that directory, run these commands:
example% ln -s stdio.h stdio.h.SUNWCCh example% ln -s cstdio cstdio.SUNWCCh |
Use the option -I/myproject/mydir on every compilation.
If you replace any C headers, you must replace them in pairs. For example, if you replace <time.h>, you should also replace <ctime>.
Replacement headers must have the same effects as the versions being replaced. That is, the various runtime libraries such as libCrun, libC, libCstd, libc, and librwtool are built using the definitions in the standard headers. If your replacements do not match, your program is unlikely to work.
When compiling in default (standard) mode, the compiler has access to the complete library specified by the C++ standard. The library components include what is informally known as the Standard Template Library (STL), as well as the following components.
string classes
numeric classes
the standard version of stream I/O classes
basic memory allocation
exception classes
run-time type information
The term STL does not have a formal definition, but is usually understood to include containers, iterators, and algorithms. The following subset of the standard library headers can be thought of as comprising the STL.
<algorithm>
<deque>
<iterator>
<list>
<map>
<memory>
<queue>
<set>
<stack>
<utility>
<vector>
The C++ standard library (libCstd) is based on the RogueWaveTM Standard C++ Library, Version 2. This library is available only for the default mode (-compat=5) of the compiler and is not supported with use of the -compat[=4] option.
The C++ compiler also supports STLport’s Standard Library implementation version 4.5.3. libCstd is still the default library, but STLport’s product is available as an alternative. See 13.3 STLport for more information.
If you need to use your own version of the C++ standard library instead of one of the versions that is supplied with the compiler, you can do so by specifying the -library=no%Cstd option. Replacing the standard library that is distributed with the compiler is risky, and good results are not guaranteed. For more information, see 12.7 Replacing the C++ Standard Library.
For details about the standard library, see the Standard C++ Library User’s Guide and the Standard C++ Class Library Reference. Accessing Sun Studio Documentation in “Before You Begin” at the front of this book contains information about accessing this documentation. For a list of available books about the C++ standard library see Commercially Available Books in “Before You Begin.”
Table 13–1 lists the headers for the complete standard library along with a brief description of each.
Table 13–1 C++ Standard Library Header Files
Header File |
Description |
---|---|
<algorithm> |
Standard algorithms that operate on containers |
<bitset> |
Fixed-size sequences of bits |
<complex> |
The numeric type representing complex numbers |
<deque> |
Sequences supporting addition and removal at each end |
<exception> |
Predefined exception classes |
<fstream> |
Stream I/O on files |
<functional> |
Function objects |
<iomanip> |
iostream manipulators |
<ios> |
iostream base classes |
<iosfwd> |
Forward declarations of iostream classes |
<iostream> |
Basic stream I/O functionality |
<istream> |
Input I/O streams |
<iterator> |
Class for traversing a sequence |
<limits> |
Properties of numeric types |
<list> |
Ordered sequences |
<locale> |
Support for internationalization |
<map> |
Associative containers with key/value pairs |
<memory> |
Special memory allocators |
<new> |
Basic memory allocation and deallocation |
<numeric> |
Generalized numeric operations |
<ostream> |
Output I/O streams |
<queue> |
Sequences supporting addition at the head and removal at the tail |
<set> |
Associative container with unique keys |
<sstream> |
Stream I/O using an in-memory string as source or sink |
<stack> |
Sequences supporting addition and removal at the head |
<stdexcept> |
Additional standard exception classes |
<streambuf> |
Buffer classes for iostreams |
<string> |
Sequences of characters |
<typeinfo> |
Run-time type identification |
<utility> |
Comparison operators |
<valarray> |
Value arrays useful for numeric programming |
<vector> |
Sequences supporting random access |
Table 13–2 lists the documentation available for each of the components of the standard library.
Table 13–2 Man Pages for C++ Standard Library
Man Page |
Overview |
---|---|
Algorithms |
Generic algorithms for performing various operations on containers and sequences |
Associative_Containers |
Ordered containers |
Bidirectional_Iterators |
An iterator that can both read and write and can traverse a container in both directions |
Containers |
A standard template library (STL) collection |
Forward_Iterators |
A forward-moving iterator that can both read and write |
Function_Objects |
Object with an operator() defined |
Heap_Operations |
See entries for make_heap, pop_heap, push_heap and sort_heap |
Input_Iterators |
A read-only, forward moving iterator |
Insert_Iterators |
An iterator adaptor that allows an iterator to insert into a container rather than overwrite elements in the container |
Iterators |
Pointer generalizations for traversal and modification of collections |
Negators |
Function adaptors and function objects used to reverse the sense of predicate function objects |
Operators |
Operators for the C++ Standard Template Library Output |
Output_Iterators |
A write-only, forward moving iterator |
Predicates |
A function or a function object that returns a boolean (true/false) value or an integer value |
Random_Access_Iterators |
An iterator that reads, writes, and allows random access to a container |
Sequences |
A container that organizes a set of sequences |
Stream_Iterators |
Includes iterator capabilities for ostreams and istreams that allow generic algorithms to be used directly on streams |
__distance_type |
Determines the type of distance used by an iterator— obsolete |
__iterator_category |
Determines the category to which an iterator belongs—obsolete |
__reverse_bi_iterator |
An iterator that traverses a collection backwards |
accumulate |
Accumulates all elements within a range into a single value |
adjacent_difference |
Outputs a sequence of the differences between each adjacent pair of elements in a range |
adjacent_find |
Find the first adjacent pair of elements in a sequence that are equivalent |
advance |
Moves an iterator forward or backward (if available) by a certain distance |
allocator |
The default allocator object for storage management in Standard Library containers |
auto_ptr |
A simple, smart pointer class |
back_insert_iterator |
An insert iterator used to insert items at the end of a collection |
back_inserter |
An insert iterator used to insert items at the end of a collection |
basic_filebuf |
Class that associates the input or output sequence with a file |
basic_fstream |
Supports reading and writing of named files or devices associated with a file descriptor |
basic_ifstream |
Supports reading from named files or other devices associated with a file descriptor |
basic_ios |
A base class that includes the common functions required by all streams |
basic_iostream |
Assists in formatting and interpreting sequences of characters controlled by a stream buffer |
basic_istream |
Assists in reading and interpreting input from sequences controlled by a stream buffer |
basic_istringstream |
Supports reading objects of class basic_string<charT,traits,Allocator> from an array in memory |
basic_ofstream |
Supports writing into named files or other devices associated with a file descriptor |
basic_ostream |
Assists in formatting and writing output to sequences controlled by a stream buffer |
basic_ostringstream |
Supports writing objects of class basic_string<charT,traits,Allocator> |
basic_streambuf |
Abstract base class for deriving various stream buffers to facilitate control of character sequences |
basic_string |
A templatized class for handling sequences of character-like entities |
basic_stringbuf |
Associates the input or output sequence with a sequence of arbitrary characters |
basic_stringstream |
Supports writing and reading objects of class basic_string<charT,traits,Allocator> to or from an array in memory |
binary_function |
Base class for creating binary function objects |
binary_negate |
A function object that returns the complement of the result of its binary predicate |
binary_search |
Performs a binary search for a value on a container |
bind1st |
Templatized utilities to bind values to function objects |
bind2nd |
Templatized utilities to bind values to function objects |
binder1st |
Templatized utilities to bind values to function objects |
binder2nd |
Templatized utilities to bind values to function objects |
bitset |
A template class and related functions for storing and manipulating fixed-size sequences of bits |
cerr |
Controls output to an unbuffered stream buffer associated with the object stderr declared in <cstdio> |
char_traits |
A traits class with types and operations for the basic_string container and iostream classes |
cin |
Controls input from a stream buffer associated with the object stdin declared in <cstdio> |
clog |
Controls output to a stream buffer associated with the object stderr declared in <cstdio> |
codecvt |
A code conversion facet |
codecvt_byname |
A facet that includes code set conversion classification facilities based on the named locales |
collate |
A string collation, comparison, and hashing facet |
collate_byname |
A string collation, comparison, and hashing facet |
compare |
A binary function or a function object that returns true or false |
complex |
C++ complex number library |
copy |
Copies a range of elements |
copy_backward |
Copies a range of elements |
count |
Count the number of elements in a container that satisfy a given condition |
count_if |
Count the number of elements in a container that satisfy a given condition |
cout |
Controls output to a stream buffer associated with the object stdout declared in <cstdio> |
ctype |
A facet that includes character classification facilities |
ctype_byname |
A facet that includes character classification facilities based on the named locales |
deque |
A sequence that supports random access iterators and efficient insertion/deletion at both beginning and end |
distance |
Computes the distance between two iterators |
divides |
Returns the result of dividing its first argument by its second |
equal |
Compares two ranges for equality |
equal_range |
Finds the largest subrange in a collection into which a given value can be inserted without violating the ordering of the collection |
equal_to |
A binary function object that returns true if its first argument equals its second |
exception |
A class that supports logic and runtime errors |
facets |
A family of classes used to encapsulate categories of locale functionality |
filebuf |
Class that associates the input or output sequence with a file |
fill |
Initializes a range with a given value |
fill_n |
Initializes a range with a given value |
find |
Finds an occurrence of value in a sequence |
find_end |
Finds the last occurrence of a sub-sequence in a sequence |
find_first_of |
Finds the first occurrence of any value from one sequence in another sequence |
find_if |
Finds an occurrence of a value in a sequence that satisfies a specified predicate |
for_each |
Applies a function to each element in a range |
fpos |
Maintains position information for the iostream classes |
front_insert_iterator |
An insert iterator used to insert items at the beginning of a collection |
front_inserter |
An insert iterator used to insert items at the beginning of a collection |
fstream |
Supports reading and writing of named files or devices associated with a file descriptor |
generate |
Initialize a container with values produced by a value-generator class |
generate_n |
Initialize a container with values produced by a value-generator class |
get_temporary_buffer |
Pointer based primitive for handling memory |
greater |
A binary function object that returns true if its first argument is greater than its second |
greater_equal |
A binary function object that returns true if its first argument is greater than or equal to its second |
gslice |
A numeric array class used to represent a generalized slice from an array |
gslice_array |
A numeric array class used to represent a BLAS-like slice from a valarray |
has_facet |
A function template used to determine if a locale has a given facet |
ifstream |
Supports reading from named files or other devices associated with a file descriptor |
includes |
A basic set of operation for sorted sequences |
indirect_array |
A numeric array class used to represent elements selected from a valarray |
inner_product |
Computes the inner product A X B of two ranges A and B |
inplace_merge |
Merges two sorted sequences into one |
insert_iterator |
An insert iterator used to insert items into a collection rather than overwrite the collection |
inserter |
An insert iterator used to insert items into a collection rather than overwrite the collection |
ios |
A base class that includes the common functions required by all streams |
ios_base |
Defines member types and maintains data for classes that inherit from it |
iosfwd |
Declares the input/output library template classes and specializes them for wide and tiny characters |
isalnum |
Determines if a character is alphabetic or numeric |
isalpha |
Determines if a character is alphabetic |
iscntrl |
Determines if a character is a control character |
isdigit |
Determines if a character is a decimal digit |
isgraph |
Determines if a character is a graphic character |
islower |
Determines whether a character is lower case |
isprint |
Determines if a character is printable |
ispunct |
Determines if a character is punctuation |
isspace |
Determines if a character is a space |
istream |
Assists in reading and interpreting input from sequences controlled by a stream buffer |
istream_iterator |
A stream iterator that has iterator capabilities for istreams |
istreambuf_iterator |
Reads successive characters from the stream buffer for which it was constructed |
istringstream |
Supports reading objects of class basic_string<charT,traits,Alocator>from an array in memory |
istrstream |
Reads characters from an array in memory |
isupper |
Determines whether a character is upper case |
isxdigit |
Determines whether a character is a hexadecimal digit |
iter_swap |
Exchanges values in two locations |
iterator |
A base iterator class |
iterator_traits |
Returns basic information about an iterator |
less |
A binary function object that returns true if tis first argument is less than its second |
less_equal |
A binary function object that returns true if its first argument is less than or equal to its second |
lexicographical_compare |
Compares two ranges lexicographically |
limits |
Refer to numeric_limits |
list |
A sequence that supports bidirectional iterators |
locale |
A localization class containing a polymorphic set of facets |
logical_and |
A binary function object that returns true if both of its arguments are true |
logical_not |
A unary function object that returns true if its argument is false |
logical_or |
A binary function object that returns true if either of its arguments are true |
lower_bound |
Determines the first valid position for an element in a sorted container |
make_heap |
Creates a heap |
map |
An associative container with access to non-key values using unique keys |
mask_array |
A numeric array class that gives a masked view of a valarray |
max |
Finds and returns the maximum of a pair of values |
max_element |
Finds the maximum value in a range |
mem_fun |
Function objects that adapt a pointer to a member function, to take the place of a global function |
mem_fun1 |
Function objects that adapt a pointer to a member function, to take the place of a global function |
mem_fun_ref |
Function objects that adapt a pointer to a member function, to take the place of a global function |
mem_fun_ref1 |
Function objects that adapt a pointer to a member function, to take the place of a global function |
merge |
Merges two sorted sequences into a third sequence |
messages |
Messaging facets |
messages_byname |
Messaging facets |
min |
Finds and returns the minimum of a pair of values |
min_element |
Finds the minimum value in a range |
minus |
Returns the result of subtracting its second argument from its first |
mismatch |
Compares elements from two sequences and returns the first two elements that don’t match each other |
modulus |
Returns the remainder obtained by dividing the first argument by the second argument |
money_get |
Monetary formatting facet for input |
money_put |
Monetary formatting facet for output |
moneypunct |
Monetary punctuation facets |
moneypunct_byname |
Monetary punctuation facets |
multimap |
An associative container that gives access to non-key values using keys |
multiplies |
A binary function object that returns the result of multiplying its first and second arguments |
multiset |
An associative container that allows fast access to stored key values |
negate |
Unary function object that returns the negation of its argument |
next_permutation |
Generates successive permutations of a sequence based on an ordering function |
not1 |
A function adaptor used to reverse the sense of a unary predicate function object |
not2 |
A function adaptor used to reverse the sense of a binary predicate function object |
not_equal_to |
A binary function object that returns true if its first argument is not equal to its second |
nth_element |
Rearranges a collection so that all elements lower in sorted order than the nth element come before it and all elements higher in sorter order than the nth element come after it |
num_get |
A numeric formatting facet for input |
num_put |
A numeric formatting facet for output |
numeric_limits |
A class for representing information about scalar types |
numpunct |
A numeric punctuation facet |
numpunct_byname |
A numeric punctuation facet |
ofstream |
Supports writing into named files or other devices associated with a file descriptor |
ostream |
Assists in formatting and writing output to sequences controlled by a stream buffer |
ostream_iterator |
Stream iterators allow for use of iterators with ostreams and istreams |
ostreambuf_iterator |
Writes successive characters onto the stream buffer object from which it was constructed |
ostringstream |
Supports writing objects of class basic_string<charT,traits,Allocator> |
ostrstream |
Writes to an array in memory |
pair |
A template for heterogeneous pairs of values |
partial_sort |
Templatized algorithm for sorting collections of entities |
partial_sort_copy |
Templatized algorithm for sorting collections of entities |
partial_sum |
Calculates successive partial sums of a range of values |
partition |
Places all of the entities that satisfy the given predicate before all of the entities that do not |
permutation |
Generates successive permutations of a sequence based on an ordering function |
plus |
A binary function object that returns the result of adding its first and second arguments |
pointer_to_binary_function |
A function object that adapts a pointer to a binary function, to take the place of a binary_function |
pointer_to_unary_function |
A function object class that adapts a pointer to a function, to take the place of a unary_function |
pop_heap |
Moves the largest element off the heap |
prev_permutation |
Generates successive permutations of a sequence based on an ordering function |
priority_queue |
A container adapter that behaves like a priority queue |
ptr_fun |
A function that is overloaded to adapt a pointer to a function, to take the place of a function |
push_heap |
Places a new element into a heap |
queue |
A container adaptor that behaves like a queue (first in, first out) |
random_shuffle |
Randomly shuffles elements of a collection |
raw_storage_iterator |
Enables iterator-based algorithms to store results into uninitialized memory |
remove |
Moves desired elements to the front of a container, and returns an iterator that describes where the sequence of desired elements ends |
remove_copy |
Moves desired elements to the front of a container, and returns an iterator that describes where the sequence of desired elements ends |
remove_copy_if |
Moves desired elements to the front of a container, and returns an iterator that describes where the sequence of desired elements ends |
remove_if |
Moves desired elements to the front of a container, and returns an iterator that describes where the sequence of desired elements ends |
replace |
Substitutes elements in a collection with new values |
replace_copy |
Substitutes elements in a collection with new values, and moves the revised sequence into result |
replace_copy_if |
Substitutes elements in a collection with new values, and moves the revised sequence into result |
replace_if |
Substitutes elements in a collection with new values |
return_temporary_buffer |
A pointer-based primitive for handling memory |
reverse |
Reverses the order of elements in a collection |
reverse_copy |
Reverses the order of elements in a collection while copying them to a new collection |
reverse_iterator |
An iterator that traverses a collection backwards |
rotate |
Swaps the segment that contains elements from first through middle-minus-one with the segment that contains the elements from middle through last |
rotate_copy |
Swaps the segment that contains elements from first through middle-minus-one with the segment that contains the elements from middle through last |
search |
Finds a sub-sequence within a sequence of values that is element-wise equal to the values in an indicated range |
search_n |
Finds a sub-sequence within a sequence of values that is element-wise equal to the values in an indicated range |
set |
An associative container that supports unique keys |
set_difference |
A basic set operation for constructing a sorted difference |
set_intersection |
A basic set operation for constructing a sorted intersection |
set_symmetric_difference |
A basic set operation for constructing a sorted symmetric difference |
set_union |
A basic set operation for constructing a sorted union |
slice |
A numeric array class for representing a BLAS-like slice from an array |
slice_array |
A numeric array class for representing a BLAS-like slice from a valarray |
smanip |
Helper classes used to implement parameterized manipulators |
smanip_fill |
Helper classes used to implement parameterized manipulators |
sort |
A templatized algorithm for sorting collections of entities |
sort_heap |
Converts a heap into a sorted collection |
stable_partition |
Places all of the entities that satisfy the given predicate before all of the entities that do not, while maintaining the relative order of elements in each group |
stable_sort |
A templatized algorithm for sorting collections of entities |
stack |
A container adapter that behaves like a stack (last in, first out) |
streambuf |
Abstract base class for deriving various stream buffers to facilitate control of character sequences |
string |
A typedef for basic_string<char, char_traits<char>, allocator<char>> |
stringbuf |
Associates the input or output sequence with a sequence of arbitrary characters |
stringstream |
Supports writing and reading objects of class basic_string<charT,traits,Alocator>to/from an array in memory |
strstream |
Reads and writes to an array in memory |
strstreambuf |
Associates either the input sequence or the output sequence with a tiny character array whose elements store arbitrary values |
swap |
Exchanges values |
swap_ranges |
Exchanges a range of values in one location with those in another |
time_get |
A time formatting facet for input |
time_get_byname |
A time formatting facet for input, based on the named locales |
time_put |
A time formatting facet for output |
time_put_byname |
A time formatting facet for output, based on the named locales |
tolower |
Converts a character to lower case. |
toupper |
Converts a character to upper case |
transform |
Applies an operation to a range of values in a collection and stores the result |
unary_function |
A base class for creating unary function objects |
unary_negate |
A function object that returns the complement of the result of its unary predicate |
uninitialized_copy |
An algorithm that uses construct to copy values from one range to another location |
uninitialized_fill |
An algorithm that uses the construct algorithm for setting values in a collection |
uninitialized_fill_n |
An algorithm that uses the construct algorithm for setting values in a collection |
unique |
Removes consecutive duplicates from a range of values and places the resulting unique values into the result |
unique_copy |
Removes consecutive duplicates from a range of values and places the resulting unique values into the result |
upper_bound |
Determines the last valid position for a value in a sorted container |
use_facet |
A template function used to obtain a facet |
valarray |
An optimized array class for numeric operations |
vector |
A sequence that supports random access iterators |
wcerr |
Controls output to an unbuffered stream buffer associated with the object stderr declared in <cstdio> |
wcin |
Controls input from a stream buffer associated with the object stdin declared in <cstdio> |
wclog |
Controls output to a stream buffer associated with the object stderr declared in <cstdio> |
wcout |
Controls output to a stream buffer associated with the object stdout declared in <cstdio> |
wfilebuf |
Class that associates the input or output sequence with a file |
wfstream |
Supports reading and writing of named files or devices associated with a file descriptor |
wifstream |
Supports reading from named files or other devices associated with a file descriptor |
wios |
A base class that includes the common functions required by all streams |
wistream |
Assists in reading and interpreting input from sequences controlled by a stream buffer |
wistringstream |
Supports reading objects of class basic_string<charT,traits,Allocator>from an array in memory |
wofstream |
Supports writing into named files or other devices associated with a file descriptor |
wostream |
Assists in formatting and writing output to sequences controlled by a stream buffer |
wostringstream |
Supports writing objects of class basic_string<charT,traits,Allocator> |
wstreambuf |
Abstract base class for deriving various stream buffers to facilitate control of character sequences |
wstring |
A typedef for basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t>> |
wstringbuf |
Associates the input or output sequence with a sequence of arbitrary characters |
Use the STLport implementation of the standard library if you wish to use an alternative standard library to libCstd. You can issue the following compiler option to turn off libCstd and use the STLport library instead:
-library=stlport4
See A.2.49 -library=l[,l...] for more information.
This release includes both a static archive called libstlport.a and a dynamic library called libstlport.so.
Consider the following information before you decide whether or not you are going to use the STLport implementation:
STLport is an open source product and does not guarantee compatibility across different releases. In other words, compiling with a future version of STLport may break applications compiled with STLport 4.5.3. It also might not be possible to link binaries compiled using STLport 4.5.3 with binaries compiled using a future version of STLport.
The stlport4, Cstd and iostream libraries provide their own implementation of I/O streams. Specifying more than one of these with the -library option can result in undefined program behavior.
Future releases of the compiler might not include STLport4. They might include only a later version of STLport. The compiler option -library=stlport4 might not be available in future releases, but could be replaced by an option referring to a later STLport version.
Tools.h++ is not supported with STLport.
STLport is binary incompatible with the default libCstd. If you use the STLport implementation of the standard library, then you must compile and link all files, including third-party libraries, with the option -library=stlport4. This means, for example, that you cannot use the STLport implementation and the C++ interval math library libCsunimath together. The reason for this is that libCsunimath was compiled with the default library headers, not with STLport.
If you decide to use the STLport implementation, be certain to include header files that your code implicitly references. The standard headers are allowed, but not required, to include one another as part of the implementation.
You cannot use the STLport implementation if you compile with -compat=4.
See the Runtime Libraries Readme for a list of libraries and object files that you can redistribute with your executables or libraries under the terms of the End User Object Code License. The C++ section of this readme lists which version of the STLport .so this release of the compiler supports. This readme is available as part of the installed product. To view the HTML version of this readme, point your browser to the default installation directory:
file:/opt/SUNWspro/docs/index.html
If your product software is not installed in the default directory, ask your system administrator for the equivalent path on your system.
The following test case does not compile with STLport because the code in the test case makes unportable assumptions about the library implementation. In particular, it assumes that either <vector> or <iostream> automatically include <iterator>, which is not a valid assumption.
#include <vector> #include <iostream> using namespace std; int main () { vector <int> v1 (10); vector <int> v3 (v1.size()); for (int i = 0; i < v1.size (); i++) {v1[i] = i; v3[i] = i;} vector <int> v2(v1.size ()); copy_backward (v1.begin (), v1.end (), v2.end ()); ostream_iterator<int> iter (cout, " "); copy (v2.begin (), v2.end (), iter); cout << endl; return 0; } |
To fix the problem, include <iterator> in the source.
C++, like C, has no built-in input or output statements. Instead, I/O facilities are provided by a library. The C++ compiler provides both the classic implementation and the ISO standard implementation of the iostream classes.
In compatibility mode (-compat[=4]), the classic iostream classes are contained in libC.
In standard mode (default mode), the classic iostream classes are contained in libiostream. Use libiostream when you have source code that uses the classic iostream classes and you want to compile the source in standard mode. To use the classic iostream facilities in standard mode, include the iostream.h header file and compile using the -library=iostream option.
The standard iostream classes are available only in standard mode, and are contained in the C++ standard library, libCstd.
This chapter provides an introduction to the classic iostream library and provides examples of its use. This chapter does not provide a complete description of the iostream library. See the iostream library man pages for more details. To access the classic iostream man pages type:man -s 3CC4name
There are four predefined iostreams:
The predefined iostreams are fully buffered, except for cerr. See 14.3.1 Output Using iostream and 14.3.2 Input Using iostream.
By including the iostream library, a program can use any number of input or output streams. Each stream has some source or sink, which may be one of the following:
Standard input
Standard output
Standard error
A file
An array of characters
A stream can be restricted to input or output, or a single stream can allow both input and output. The iostream library implements these streams using two processing layers.
The lower layer implements sequences, which are simply streams of characters. These sequences are implemented by the streambuf class, or by classes derived from it.
The upper layer performs formatting operations on sequences. These formatting operations are implemented by the istream and ostream classes, which have as a member an object of a type derived from class streambuf. An additional class, iostream, is for streams on which both input and output can be performed.
Standard input, output, and error are handled by special class objects derived from class istream or ostream.
The ifstream, ofstream, and fstream classes, which are derived from istream, ostream, and iostream respectively, handle input and output with files.
The istrstream, ostrstream, and strstream classes, which are derived from istream, ostream, and iostream respectively, handle input and output to and from arrays of characters.
When you open an input or output stream, you create an object of one of these types, and associate the streambuf member of the stream with a device or file. You generally do this association through the stream constructor, so you don’t work with the streambuf directly. The iostream library predefines stream objects for the standard input, standard output, and error output, so you don’t have to create your own objects for those streams.
You use operators or iostream member functions to insert data into a stream (output) or extract data from a stream (input), and to control the format of data that you insert or extract.
When you want to insert and extract a new data type—one of your classes—you generally overload the insertion and extraction operators.
To use routines from the classic iostream library, you must include the header files for the part of the library you need. The header files are described in the following table.
Table 14–1 iostream Routine Header Files
You usually do not need all of these header files in your program. Include only the ones that contain the declarations you need. In compatibility mode (-compat[=4]), the classic iostream library is part of libC, and is linked automatically by the CC driver. In standard mode (the default), libiostream contains the classic iostream library.
Output using iostream usually relies on the overloaded left-shift operator (<<) which, in the context of iostream, is called the insertion operator. To output a value to standard output, you insert the value in the predefined output stream cout. For example, given a value someValue, you send it to standard output with a statement like:
cout << someValue; |
The insertion operator is overloaded for all built-in types, and the value represented by someValue is converted to its proper output representation. If, for example, someValue is a float value, the << operator converts the value to the proper sequence of digits with a decimal point. Where it inserts float values on the output stream, << is called the float inserter. In general, given a type X, << is called the X inserter. The format of output and how you can control it is discussed in the ios(3CC4) man page.
The iostream library does not support user-defined types. If you define types that you want to output in your own way, you must define an inserter (that is, overload the << operator) to handle them correctly.
The << operator can be applied repetitively. To insert two values on cout, you can use a statement like the one in the following example:
cout << someValue << anotherValue; |
The output from the above example will show no space between the two values. So you may want to write the code this way:
cout << someValue << " " << anotherValue; |
The << operator has the precedence of the left shift operator (its built-in meaning). As with other operators, you can always use parentheses to specify the order of action. It is often a good idea to use parentheses to avoid problems of precedence. Of the following four statements, the first two are equivalent, but the last two are not.
cout << a+b; // + has higher precedence than << cout << (a+b); cout << (a&y); // << has precedence higher than & cout << a&y; // probably an error: (cout << a) & y |
The following example defines a string class:
#include <stdlib.h> #include <iostream.h> class string { private: char* data; size_t size; public: // (functions not relevant here) friend ostream& operator<<(ostream&, const string&); friend istream& operator>>(istream&, string&); }; |
The insertion and extraction operators must in this case be defined as friends because the data part of the string class is private.
ostream& operator<< (ostream& ostr, const string& output) { return ostr << output.data;} |
Here is the definition of operator<< overloaded for use with strings.
cout << string1 << string2; |
operator<< takes ostream& (that is, a reference to an ostream) as its first argument and returns the same ostream, making it possible to combine insertions in one statement.
Generally, you don’t have to check for errors when you overload operator<< because the iostream library is arranged to propagate errors.
When an error occurs, the iostream where it occurred enters an error state. Bits in the iostream’s state are set according to the general category of the error. The inserters defined in iostream ignore attempts to insert data into any stream that is in an error state, so such attempts do not change the iostream’s state.
In general, the recommended way to handle errors is to periodically check the state of the output stream in some central place. If there is an error, you should handle it in some way. This chapter assumes that you define a function error, which takes a string and aborts the program. error is not a predefined function. See 14.3.9 Handling Input Errors for an example of an error function. You can examine the state of an iostream with the operator !,which returns a nonzero value if the iostream is in an error state. For example:
if (!cout) error("output error"); |
There is another way to test for errors. The ios class defines operator void *(), so it returns a NULL pointer when there is an error. You can use a statement like:
if (cout << x) return; // return if successful |
You can also use the function good, a member of ios:
if (cout.good()) return; // return if successful |
The error bits are declared in the enum:
enum io_state {goodbit=0, eofbit=1, failbit=2, badbit=4, hardfail=0x80}; |
For details on the error functions, see the iostream man pages.
As with most I/O libraries, iostream often accumulates output and sends it on in larger and generally more efficient chunks. If you want to flush the buffer, you simply insert the special value flush. For example:
cout << "This needs to get out immediately." << flush; |
flush is an example of a kind of object known as a manipulator, which is a value that can be inserted into an iostream to have some effect other than causing output of its value. It is really a function that takes an ostream& or istream& argument and returns its argument after performing some actions on it (see 14.7 Manipulators).
To obtain output in the raw binary form of a value, use the member function write as shown in the following example. This example shows the output in the raw binary form of x.
cout.write((char*)&x, sizeof(x)); |
The previous example violates type discipline by converting &x to char*. Doing so is normally harmless, but if the type of x is a class with pointers, virtual member functions, or one that requires nontrivial constructor actions, the value written by the above example cannot be read back in properly.
Input using iostream is similar to output. You use the extraction operator >> and you can string together extractions the way you can with insertions. For example:
cin >> a >> b; |
This statement gets two values from standard input. As with other overloaded operators, the extractors used depend on the types of a and b (and two different extractors are used if a and b have different types). The format of input and how you can control it is discussed in some detail in the ios(3CC4) man page. In general, leading whitespace characters (spaces, newlines, tabs, form-feeds, and so on) are ignored.
When you want input for a new type, you overload the extraction operator for it, just as you overload the insertion operator for output.
Class string defines its extraction operator in the following code example:
istream& operator>> (istream& istr, string& input) { const int maxline = 256; char holder[maxline]; istr.get(holder, maxline, ”\n’); input = holder; return istr; } |
The get function reads characters from the input stream istr and stores them in holder until maxline-1 characters have been read, or a new line is encountered, or EOF, whichever happens first. The data in holder is then null-terminated. Finally, the characters in holder are copied into the target string.
By convention, an extractor converts characters from its first argument (in this case, istream& istr), stores them in its second argument, which is always a reference, and returns its first argument. The second argument must be a reference because an extractor is meant to store the input value in its second argument.
This predefined extractor is mentioned here because it can cause problems. Use it like this:
char x[50]; cin >> x; |
This extractor skips leading whitespace and extracts characters and copies them to x until it reaches another whitespace character. It then completes the string with a terminating null (0) character. Be careful, because input can overflow the given array.
You must also be sure the pointer points to allocated storage. For example, here is a common error:
char * p; // not initialized cin >> p; |
There is no telling where the input data will be stored, and it may cause your program to abort.
In addition to using the char extractor, you can get a single character with either form of the get member function. For example:
char c; cin.get(c); // leaves c unchanged if input fails int b; b = cin.get(); // sets b to EOF if input fails |
Unlike the other extractors, the char extractor does not skip leading whitespace.
Here is a way to skip only blanks, stopping on a tab, newline, or any other character:
int a; do { a = cin.get(); } while(a ==’ ’); |
If you need to read binary values (such as those written with the member function write), you can use the read member function. The following example shows how to input the raw binary form of x using the read member function, and is the inverse of the earlier example that uses write.
cin.read((char*)&x, sizeof(x)); |
You can use the peek member function to look at the next character in the stream without extracting it. For example:
if (cin.peek()!= c) return 0; |
By default, the iostream extractors skip leading whitespace. You can turn off the skip flag to prevent this from happening. The following example turns off whitespace skipping from cin, then turns it back on:
cin.unsetf(ios::skipws); // turn off whitespace skipping ... cin.setf(ios::skipws); // turn it on again |
You can use the iostream manipulator ws to remove leading whitespace from the iostream, whether or not skipping is enabled. The following example shows how to remove the leading whitespace from iostream istr:
istr >> ws; |
By convention, an extractor whose first argument has a nonzero error state should not extract anything from the input stream and should not clear any error bits. An extractor that fails should set at least one error bit.
As with output errors, you should check the error state periodically and take some action, such as aborting, when you find a nonzero state. The ! operator tests the error state of an iostream. For example, the following code produces an input error if you type alphabetic characters for input:
#include <stdlib.h> #include <iostream.h> void error (const char* message) { cerr << message << "\n"; exit(1); } int main() { cout << "Enter some characters: "; int bad; cin >> bad; if (!cin) error("aborted due to input error"); cout << "If you see this, not an error." << "\n"; return 0; } |
Class ios has member functions that you can use for error handling. See the man pages for details.
You can use stdio with C++ programs, but problems can occur when you mix iostreams and stdio in the same standard stream within a program. For example, if you write to both stdout and cout, independent buffering occurs and produces unexpected results. The problem is worse if you input from both stdin and cin, since independent buffering may turn the input into trash.
To eliminate this problem with standard input, standard output and standard error, use the following instruction before performing any input or output. It connects all the predefined iostreams with the corresponding predefined stdio FILEs.
ios::sync_with_stdio(); |
Such a connection is not the default because there is a significant performance penalty when the predefined streams are made unbuffered as part of the connection. You can use both stdio and iostreams in the same program applied to different files. That is, you can write to stdout using stdio routines and write to other files attached to iostreams. You can open stdio FILEs for input and also read from cin so long as you don’t also try to read from stdin.
To read or write a stream other than the predefined iostreams, you need to create your own iostream. In general, that means creating objects of types defined in the iostream library. This section discusses the various types available.
Dealing with files is similar to dealing with standard input and standard output; classes ifstream, ofstream, and fstream are derived from classes istream, ostream, and iostream, respectively. As derived classes, they inherit the insertion and extraction operations (along with the other member functions) and also have members and constructors for use with files.
Include the file fstream.h to use any of the fstreams. Use an ifstream when you only want to perform input, an ofstream for output only, and an fstream for a stream on which you want to perform both input and output. Use the name of the file as the constructor argument.
For example, copy the file thisFile to the file thatFile as in the following example:
ifstream fromFile("thisFile"); if (!fromFile) error("unable to open ’thisFile’ for input"); ofstream toFile ("thatFile"); if (!toFile) error("unable to open ’thatFile’ for output"); char c; while (toFile && fromFile.get(c)) toFile.put(c); |
This code:
Creates an ifstream object called fromFile with a default mode of ios::in and connects it to thisFile. It opens thisFile.
Checks the error state of the new ifstream object and, if it is in a failed state, calls the error function, which must be defined elsewhere in the program.
Creates an ofstream object called toFile with a default mode of ios::out and connects it to thatFile.
Checks the error state of toFile as above.
Creates a char variable to hold the data while it is passed.
Copies the contents of fromFile to toFile one character at a time.
It is, of course, undesirable to copy a file this way, one character at a time. This code is provided just as an example of using fstreams. You should instead insert the streambuf associated with the input stream into the output stream. See 14.10 Streambufs, and the man page sbufpub(3CC4).
The mode is constructed by or-ing bits from the enumerated type open_mode, which is a public type of class ios and has the definition:
enum open_mode {binary=0, in=1, out=2, ate=4, app=8, trunc=0x10, nocreate=0x20, noreplace=0x40}; |
The binary flag is not needed on UNIX, but is provided for compatibility with systems that do need it. Portable code should use the binary flag when opening binary files.
You can open a file for both input and output. For example, the following code opens file someName for both input and output, attaching it to the fstream variable inoutFile.
fstream inoutFile("someName", ios::in|ios::out); |
You can declare an fstream without specifying a file and open the file later. For example, the following creates the ofstream toFile for writing.
ofstream toFile; toFile.open(argv[1], ios::out); |
You can close the fstream and then open it with another file. For example, to process a list of files provided on the command line:
ifstream infile; for (char** f = &argv[1]; *f; ++f) { infile.open(*f, ios::in); ...; infile.close(); } |
If you know a file descriptor, such as the integer 1 for standard output, you can open it like this:
ofstream outfile; outfile.attach(1); |
When you open a file by providing its name to one of the fstream constructors or by using the open function, the file is automatically closed when the fstream is destroyed (by a delete or when it goes out of scope). When you attach a file to an fstream, it is not automatically closed.
You can alter the reading and writing position in a file. Several tools are supplied for this purpose.
streampos is a type that can record a position in an iostream.
tellg (tellp) is an istream (ostream) member function that reports the file position. Since istream and ostream are the parent classes of fstream, tellg and tellp can also be invoked as a member function of the fstream class.
seekg (seekp) is an istream (ostream) member function that finds a given position.
The seek_dir enum specifies relative positions for use with seek.
enum seek_dir {beg=0, cur=1, end=2}; |
For example, given an fstream aFile:
streampos original = aFile.tellp(); //save current position aFile.seekp(0, ios::end); //reposition to end of file aFile << x; //write a value to file aFile.seekp(original); //return to original position |
seekg (seekp) can take one or two parameters. When it has two parameters, the first is a position relative to the position indicated by the seek_dir value given as the second parameter. For example:
aFile.seekp(-10, ios::end); |
moves to 10 bytes from the end while
aFile.seekp(10, ios::cur); |
moves to 10 bytes forward from the current position.
Arbitrary seeks on text streams are not portable, but you can always return to a previously saved streampos value.
iostreams does not allow assignment of one stream to another.
The problem with copying a stream object is that there are then two versions of the state information, such as a pointer to the current write position within an output file, which can be changed independently. As a result, problems could occur.
Format control is discussed in detail in the in the man page ios(3CC4).
Manipulators are values that you can insert into or extract from iostreams to have special effects.
Parameterized manipulators are manipulators that take one or more parameters.
Because manipulators are ordinary identifiers, and therefore use up possible names, iostream doesn’t define them for every possible function. A number of manipulators are discussed with member functions in other parts of this chapter.
There are 13 predefined manipulators, as described in Table 14–2. When using that table, assume the following:
i has type long.
n has type int.
c has type char.
istr is an input stream.
ostr is an output stream.
To use predefined manipulators, you must include the file iomanip.h in your program.
You can define your own manipulators. There are two basic types of manipulator:
Plain manipulator—Takes an istream&, ostream&, or ios& argument, operates on the stream, and then returns its argument.
Parameterized manipulator—Takes an istream&, ostream&, or ios& argument, one additional argument (the parameter), operates on the stream, and then returns its stream argument.
A plain manipulator is a function that:
Takes a reference to a stream
Operates on it in some way
Returns its argument
The shift operators taking (a pointer to) such a function are predefined for iostreams, so the function can be put in a sequence of input or output operators. The shift operator calls the function rather than trying to read or write a value. An example of a tab manipulator that inserts a tab in an ostream is:
ostream& tab(ostream& os) { return os <<’\t’; } ... cout << x << tab << y; |
This is an elaborate way to achieve the following:
const char tab = ’\t’; ... cout << x << tab << y; |
The following code is another example, which cannot be accomplished with a simple constant. Suppose you want to turn whitespace skipping on and off for an input stream. You can use separate calls to ios::setf and ios::unsetf to turn the skipws flag on and off, or you could define two manipulators.
#include <iostream.h> #include <iomanip.h> istream& skipon(istream &is) { is.setf(ios::skipws, ios::skipws); return is; } istream& skipoff(istream& is) { is.unsetf(ios::skipws); return is; } ... int main () { int x,y; cin >> skipon >> x >> skipoff >> y; return 1; } |
One of the parameterized manipulators that is included in iomanip.h is setfill. setfill sets the character that is used to fill out field widths. It is implemented as shown in the following example:
//file setfill.cc #include<iostream.h> #include<iomanip.h> //the private manipulator static ios& sfill(ios& i, int f) { i.fill(f); return i; } //the public applicator smanip_int setfill(int f) { return smanip_int(sfill, f); } |
A parameterized manipulator is implemented in two parts:
The manipulator. It takes an extra parameter. In the previous code example, it takes an extra int parameter. You cannot place this manipulator function in a sequence of input or output operations, since there is no shift operator defined for it. Instead, you must use an auxiliary function, the applicator.
The applicator. It calls the manipulator. The applicator is a global function, and you make a prototype for it available in a header file. Usually the manipulator is a static function in the file containing the source code for the applicator. The manipulator is called only by the applicator, and if you make it static, you keep its name out of the global address space.
Several classes are defined in the header file iomanip.h. Each class holds the address of a manipulator function and the value of one parameter. The iomanip classes are described in the man page manip(3CC4). The previous example uses the smanip_int class, which works with an ios. Because it works with an ios, it also works with an istream and an ostream. The previous example also uses a second parameter of type int.
The applicator creates and returns a class object. In the previous code example the class object is an smanip_int, and it contains the manipulator and the int argument to the applicator. The iomanip.h header file defines the shift operators for this class. When the applicator function setfill appears in a sequence of input or output operations, the applicator function is called, and it returns a class. The shift operator acts on the class to call the manipulator function with its parameter value, which is stored in the class.
In the following example, the manipulator print_hex:
Puts the output stream into the hex mode.
Restores the conversion mode of the stream.
The class omanip_long is used because this code example is for output only, and it operates on a long rather than an int:
#include <iostream.h> #include <iomanip.h> static ostream& xfield(ostream& os, long v) { long save = os.setf(ios::hex, ios::basefield); os << v; os.setf(save, ios::basefield); return os; } omanip_long print_hex(long v) { return omanip_long(xfield, v); } |
See the strstream(3CC4) man page.
See the stdiobuf(3CC4) man page.
iostreams are the formatting part of a two-part (input or output) system. The other part of the system is made up of streambufs, which deal in input or output of unformatted streams of characters.
You usually use streambufs through iostreams, so you don’t have to worry about the details of streambufs. You can use streambufs directly if you choose to, for example, if you need to improve efficiency or to get around the error handling or formatting built into iostreams.
A streambuf consists of a stream or sequence of characters and one or two pointers into that sequence. Each pointer points between two characters. (Pointers cannot actually point between characters, but it is helpful to think of them that way.) There are two kinds of streambuf pointers:
A put pointer, which points just before the position where the next character will be stored
A get pointer, which points just before the next character to be fetched
A streambuf can have one or both of these pointers.
The positions of the pointers and the contents of the sequences can be manipulated in various ways. Whether or not both pointers move when manipulated depends on the kind of streambuf used. Generally, with queue-like streambufs, the get and put pointers move independently; with file-like streambufs the get and put pointers always move together. A strstream is an example of a queue-like stream; an fstream is an example of a file-like stream.
You never create an actual streambuf object, but only objects of classes derived from class streambuf. Examples are filebuf and strstreambuf, which are described in man pages filebuf(3CC4) and ssbuf(3), respectively. Advanced users may want to derive their own classes from streambuf to provide an interface to a special device or to provide other than basic buffering. Man pages sbufpub(3CC4) and sbufprot(3CC4) discuss how to do this.
Apart from creating your own special kind of streambuf, you may want to access the streambuf associated with an iostream to access the public member functions, as described in the man pages referenced above. In addition, each iostream has a defined inserter and extractor which takes a streambuf pointer. When a streambuf is inserted or extracted, the entire stream is copied.
Here is another way to do the file copy discussed earlier, with the error checking omitted for clarity:
ifstream fromFile("thisFile"); ofstream toFile ("thatFile"); toFile << fromFile.rdbuf(); |
We open the input and output files as before. Every iostream class has a member function rdbuf that returns a pointer to the streambuf object associated with it. In the case of an fstream, the streambuf object is type filebuf. The entire file associated with fromFile is copied (inserted into) the file associated with toFile. The last line could also be written like this:
fromFile >> toFile.rdbuf(); |
The source file is then extracted into the destination. The two methods are entirely equivalent.
A number of C++ man pages give details of the iostream library. The following table gives an overview of what is in each man page.
To access a classic iostream library man page, type:
example% man -s 3CC4 name |
Man Page |
Overview |
---|---|
filebuf |
Details the public interface for the class filebuf, which is derived from streambuf and is specialized for use with files. See the sbufpub(3CC4) and sbufprot(3CC4) man pages for details of features inherited from class streambuf. Use the filebuf class through class fstream. |
fstream |
Details specialized member functions of classes ifstream, ofstream, and fstream, which are specialized versions of istream, ostream, and iostream for use with files. |
ios |
Details parts of class ios, which functions as a base class for iostreams. It contains state data common to all streams. |
ios.intro |
Gives an introduction to and overview of iostreams. |
istream |
Details the following:
|
manip |
Describes the input and output manipulators defined in the iostream library. |
ostream |
Details the following:
|
sbufprot |
Describes the interface needed by programmers who are coding a class derived from class streambuf. Also refer to the sbufpub(3CC4) man page because some public functions are not discussed in the sbufprot(3CC4) man page. |
sbufpub |
Details the public interface of class streambuf, in particular, the public member functions of streambuf. This man page contains the information needed to manipulate a streambuf-type object directly, or to find out about functions that classes derived from streambuf inherit from it. If you want to derive a class from streambuf, also see the sbufprot(3CC4) man page. |
ssbuf |
Details the specialized public interface of class strstreambuf, which is derived from streambuf and specialized for dealing with arrays of characters. See the sbufpub(3CC4) man page for details of features inherited from class streambuf. |
stdiobuf |
Contains a minimal description of class stdiobuf, which is derived from streambuf and specialized for dealing with stdio FILEs. See the sbufpub(3CC4) man page for details of features inherited from class streambuf. |
strstream |
Details the specialized member functions of strstreams, which are implemented by a set of classes derived from the iostream classes and specialized for dealing with arrays of characters. |
The iostream library descriptions often use terms similar to terms from general programming, but with specialized meanings. The following table defines these terms as they are used in discussing the iostream library.
Table 14–4 iostream Terminology
iostream Term |
Definition |
---|---|
A word with two meanings, one specific to the iostream package and one more generally applied to input and output. When referring specifically to the iostream library, a buffer is an object of the type defined by the class streambuf. A buffer, generally, is a block of memory used to make efficient transfer of characters for input of output. With buffered I/O, the actual transfer of characters is delayed until the buffer is full or forcibly flushed. An unbuffered buffer refers to a streambuf where there is no buffer in the general sense defined above. This chapter avoids use of the term buffer to refer to streambufs. However, the man pages and other C++ documentation do use the term buffer to mean streambufs. |
|
The process of taking input from an iostream. |
|
An input or output stream specialized for use with files. Refers specifically to a class derived from class iostream when printed in courier font. |
|
The process of sending output into an iostream. |
|
Generally, an input or output stream. |
|
iostream library |
The library implemented by the include files iostream.h, fstream.h, strstream.h, iomanip.h, and stdiostream.h. Because iostream is an object-oriented library, you should extend it. So, some of what you can do with the iostream library is not implemented. |
An iostream, fstream, strstream, or user-defined stream in general. |
|
A buffer that contains a sequence of characters with a put or get pointer, or both. When printed in courier font, it means the particular class. Otherwise, it refers generally to any object of class streambuf or a class derived from streambuf. Any stream object contains an object, or a pointer to an object, of a type derived from streambuf. |
|
An iostream specialized for use with character arrays. It refers to the specific class when printed in courier font. |
Complex numbers are numbers made up of a real part and an imaginary part. For example:
3.2 + 4i 1 + 3i 1 + 2.3i
In the degenerate case, 0 + 3i is an entirely imaginary number generally written as 3i, and 5 + 0i is an entirely real number generally written as 5. You can represent complex numbers using the complex data type.
The complex arithmetic library ( libcomplex) is available only for compatibility mode ( -compat[ =4]). In standard mode (the default mode), complex number classes with similar functionality are included with the C++ Standard Library libCstd.
The complex arithmetic library implements a complex number data type as a new data type and provides:
Operators
Mathematical functions (defined for the built-in numerical types)
Extensions (for iostreams that allow input and output of complex numbers)
Error handling mechanisms
Complex numbers can also be represented as an absolute value (or magnitude) and an argument (or angle). The library provides functions to convert between the real and imaginary (Cartesian) representation and the magnitude and angle (polar) representation.
The complex conjugate of a number has the opposite sign in its imaginary part.
To use the complex library, include the header file complex.h in your program, and compile and link with the -library=complex option.
The complex arithmetic library defines one class: class complex. An object of class complex can hold a single complex number. The complex number is constructed of two parts:
The real part
The imaginary part
class complex { double re, im; }; |
The value of an object of class complex is a pair of double values. The first value represents the real part; the second value represents the imaginary part.
There are two constructors for complex. Their definitions are:
complex::complex() {re=0.0; im=0.0;} complex::complex(double r, double i = 0.0) {re=r; im=i;} |
If you declare a complex variable without specifying parameters, the first constructor is used and the variable is initialized, so that both parts are 0. The following example creates a complex variable whose real and imaginary parts are both 0:
complex aComp; |
You can give either one or two parameters. In either case, the second constructor is used. When you give only one parameter, that parameter is taken as the value for the real part and the imaginary part is set to 0. For example:
complex aComp(4.533); |
creates a complex variable with the following value:
4.533 + 0i |
If you give two values, the first value is taken as the value of the real part and the second as the value of the imaginary part. For example:
complex aComp(8.999, 2.333); |
creates a complex variable with the following value:
8.999 + 2.333i |
You can also create a complex number using the polar function, which is provided in the complex arithmetic library (see 15.3 Mathematical Functions). The polar function creates a complex value given the polar coordinates magnitude and angle.
There is no destructor for type complex.
The complex arithmetic library defines all the basic arithmetic operators. Specifically, the following operators work in the usual way and with the usual precedence:
+ - / * =
The subtraction operator (-) has its usual binary and unary meanings.
In addition, you can use the following operators in the usual way:
Addition assign operator (+=)
Subtraction assign operator (-=)
Multiplication assign operator (*=)
Division assign operator (/=)
However, the preceding four operators do not produce values that you can use in expressions. For example, the following expressions do not work:
complex a, b; ... if ((a+=2)==0) {...}; // illegal b = a *= b; // illegal |
You can also use the equality operator (==) and the inequality operator (!=) in their regular meaning.
When you mix real and complex numbers in an arithmetic expression, C++ uses the complex operator function and converts the real values to complex values.
The complex arithmetic library provides a number of mathematical functions. Some are peculiar to complex numbers; the rest are complex-number versions of functions in the standard C mathematical library.
All of these functions produce a result for every possible argument. If a function cannot produce a mathematically acceptable result, it calls complex_error and returns some suitable value. In particular, the functions try to avoid actual overflow and call complex_error with a message instead. The following tables describe the remainder of the complex arithmetic library functions.
The implementation of the sqrt and atan2 functions is aligned with the C99 csqrt Annex G specification.
Complex Arithmetic Library Function |
Description |
---|---|
double abs(const complex) |
Returns the magnitude of a complex number. |
double arg(const complex) |
Returns the angle of a complex number. |
complex conj(const complex) |
Returns the complex conjugate of its argument. |
double imag(const complex&) |
Returns the imaginary part of a complex number. |
double norm(const complex) |
Returns the square of the magnitude of its argument. Faster than abs, but more likely to cause an overflow. For comparing magnitudes. |
complex polar(double mag, double ang=0.0) |
Takes a pair of polar coordinates that represent the magnitude and angle of a complex number and returns the corresponding complex number. |
double real(const complex&) |
Returns the real part of a complex number. |
Table 15–2 Complex Mathematical and Trigonometric Functions
Description |
|
---|---|
complex acos(const complex) |
Returns the angle whose cosine is its argument. |
complex asin(const complex) |
Returns the angle whose sine is its argument. |
complex atan(const complex) |
Returns the angle whose tangent is its argument. |
complex cos(const complex) |
Returns the cosine of its argument. |
complex cosh(const complex) |
Returns the hyperbolic cosine of its argument. |
complex exp(const complex) |
Computes e**x, where e is the base of the natural logarithms, and x is the argument given to exp. |
complex log(const complex) |
Returns the natural logarithm of its argument. |
complex log10(const complex) |
Returns the common logarithm of its argument. |
complex pow(double b, const complex exp) complex pow(const complex b, int exp) complex pow(const complex b, double exp) complex pow(const complex b, const complex exp) |
Takes two arguments: pow(b, exp). It raises b to the power of exp. |
complex sin(const complex) |
Returns the sine of its argument. |
complex sinh(const complex) |
Returns the hyperbolic sine of its argument. |
complex sqrt(const complex) |
Returns the square root of its argument. |
complex tan(const complex) |
Returns the tangent of its argument. |
complex tanh(const complex) |
Returns the hyperbolic tangent of its argument. |
The complex library has these definitions for error handling:
extern int errno; class c_exception {...}; int complex_error(c_exception&); |
The external variable errno is the global error state from the C library. errno can take on the values listed in the standard header errno.h (see the man page perror(3)). No function sets errno to zero, but many functions set it to other values.
To determine whether a particular operation fails:
Set errno to zero before the operation.
Test the operation.
The function complex_error takes a reference to type c_exception and is called by the following complex arithmetic library functions:
exp
log
log10
sinh
cosh
The default version of complex_error returns zero. This return of zero means that the default error handling takes place. You can provide your own replacement function complex_error that performs other error handling. Error handling is described in the man page cplxerr(3CC4).
Default error handling is described in the man pages cplxtrig(3CC4) and cplxexp(3CC4) It is also summarized in the following table.
Complex Arithmetic Library Function |
Default Error Handling Summary |
---|---|
exp |
If overflow occurs, sets errno to ERANGE and returns a huge complex number. |
log, log10 |
If the argument is zero, sets errno to EDOM and returns a huge complex number. |
sinh, cosh |
If the imaginary part of the argument causes overflow, returns a complex zero. If the real part causes overflow, returns a huge complex number. In either case, sets errno to ERANGE. |
The complex arithmetic library provides default extractors and inserters for complex numbers, as shown in the following example:
ostream& operator<<(ostream&, const complex&); //inserter istream& operator>>(istream&, complex&); //extractor |
For basic information on extractors and inserters, see 14.2 Basic Structure of iostream Interaction and 14.3.1 Output Using iostream.
For input, the complex extractor >> extracts a pair of numbers (surrounded by parentheses and separated by a comma) from the input stream and reads them into a complex object. The first number is taken as the value of the real part; the second as the value of the imaginary part. For example, given the declaration and input statement:
complex x; cin >> x; |
and the input (3.45, 5), the value of x is equivalent to 3.45 + 5.0i. The reverse is true for inserters. Given complex x(3.45, 5), cout<<x prints (3.45, 5).
The input usually consists of a pair of numbers in parentheses separated by a comma; white space is optional. If you provide a single number, with or without parentheses and white space, the extractor sets the imaginary part of the number to zero. Do not include the symbol i in the input text.
The inserter inserts the values of the real and imaginary parts enclosed in parentheses and separated by a comma. It does not include the symbol i. The two values are treated as doubles.
Type complex is designed to fit in with the built-in arithmetic types in mixed-mode expressions. Arithmetic types are silently converted to type complex, and there are complex versions of the arithmetic operators and most mathematical functions. For example:
int i, j; double x, y; complex a, b; a = sin((b+i)/y) + x/j; |
The expression b+i is mixed-mode. Integer i is converted to type complex via the constructor complex::complex(double,double=0), the integer first being converted to type double. The result is to be divided by y, a double, so y is also converted to complex and the complex divide operation is used. The quotient is thus type complex, so the complex sine routine is called, yielding another complex result, and so on.
Not all arithmetic operations and conversions are implicit, or even defined, however. For example, complex numbers are not well-ordered, mathematically speaking, and complex numbers can be compared for equality only.
complex a, b; a == b; // OK a != b; // OK a < b; // error: operator < cannot be applied to type complex a >= b; // error: operator >= cannot be applied to type complex |
Similarly, there is no automatic conversion from type complex to any other type, because the concept is not well-defined. You can specify whether you want the real part, imaginary part, or magnitude, for example.
complex a; double f(double); f(abs(a)); // OK f(a); // error: no match for f(complex) |
The design of the complex class addresses efficiency concerns.
The simplest functions are declared inline to eliminate function call overhead.
Several overloaded versions of functions are provided when that makes a difference. For example, the pow function has versions that take exponents of type double and int as well as complex, since the computations for the former are much simpler.
The standard C math library header math.h is included automatically when you include complex.h. The C++ overloading rules then result in efficient evaluation of expressions like this:
double x; complex x = sqrt(x); |
In this example, the standard math function sqrt(double) is called, and the result is converted to type complex, rather than converting to type complex first and then calling sqrt(complex). This result falls right out of the overload resolution rules, and is precisely the result you want.
The remaining documentation of the complex arithmetic library consists of the man pages listed in the following table.
Table 15–3 Man Pages for Type complex
Man Page |
Overview |
---|---|
cplx.intro(3CC4) |
General introduction to the complex arithmetic library |
cartpol(3CC4) |
Cartesian and polar functions |
cplxerr(3CC4) |
Error-handling functions |
cplxexp(3CC4) |
Exponential, log, and square root functions |
cplxops(3CC4) |
Arithmetic operator functions |
cplxtrig(3CC4) |
Trigonometric functions |
This chapter explains how to build your own libraries.
Libraries provide two benefits. First, they provide a way to share code among several applications. If you have such code, you can create a library with it and link the library with any application that needs it. Second, libraries provide a way to reduce the complexity of very large applications. Such applications can build and maintain relatively independent portions as libraries and so reduce the burden on programmers working on other portions.
Building a library simply means creating .o files (by compiling your code with the -c option) and combining the .o files into a library using the CC command. You can build two kinds of libraries, static (archive) libraries and dynamic (shared) libraries.
With static (archive) libraries, objects within the library are linked into the program’s executable file at link time. Only those .o files from the library that are needed by the application are linked into the executable. The name of a static (archive) library generally ends with a .a suffix.
With dynamic (shared) libraries, objects within the library are not linked into the program’s executable file, but rather the linker notes in the executable that the program depends on the library. When the program is executed, the system loads the dynamic libraries that the program requires. If two programs that use the same dynamic library execute at the same time, the operating system shares the library among the programs. The name of a dynamic (shared) library ends with a .so suffix.
Linking dynamically with shared libraries has several advantages over linking statically with archive libraries:
The size of the executable is smaller.
Significant portions of code can be shared among programs at runtime, reducing the amount of memory use.
The library can be replaced at runtime without relinking with the application. (This is the primary mechanism that enables programs to take advantage of many improvements in the Solaris operating system without requiring relinking and redistribution of programs.)
The shared library can be loaded at runtime, using the dlopen() function call.
However, dynamic libraries have some disadvantages:
Runtime linking has an execution-time cost.
Distributing a program that uses dynamic libraries might require simultaneous distribution of the libraries it uses.
Moving a shared library to a different location can prevent the system from finding the library and executing the program. (The environment variable LD_LIBRARY_PATH helps overcome this problem.)
The mechanism for building static (archive) libraries is similar to that of building an executable. A collection of object (.o) files can be combined into a single library using the– xar option of CC.
You should build static (archive) libraries using CC -xar instead of using the ar command directly. The C++ language generally requires that the compiler maintain more information than can be accommodated with traditional .o files, particularly template instances. The– xar option ensures that all necessary information, including template instances, is included in the library. You might not be able to accomplish this in a normal programming environment since make might not know which template files are actually created and referenced. Without CC -xar, referenced template instances might not be included in the library, as required. For example:
% CC -c foo.cc # Compile main file, templates objects are created. % CC -xar -o foo.a foo.o # Gather all objects into a library. |
The– xar flag causes CC to create a static (archive) library. The– o directive is required to name the newly created library. The compiler examines the object files on the command line, cross-references the object files with those known to the template repository, and adds those templates required by the user’s object files (along with the main object files themselves) to the archive.
Use the -xar flag for creating or updating an existing archive only. Do not use it to maintain an archive. The -xar option is equivalent to ar -cr.
It is a good idea to have only one function in each .o file. If you are linking with an archive, an entire .o file from the archive is linked into your application when a symbol is needed from that particular .o file. Having one function in each .o file ensures that only those symbols needed by the application will be linked from the archive.
Dynamic (shared) libraries are built the same way as static (archive) libraries, except that you use– G instead of– xar on the command line.
You should not use ld directly. As with static libraries, the CC command ensures that all the necessary template instances from the template repository are included in the library if you are using templates. All static constructors in a dynamic library that is linked to an application are called before main() is executed and all static destructors are called after main() exits. If a shared library is opened using dlopen(), all static constructors are executed at dlopen() and all static destructors are executed at dlclose().
You should use CC -G to build a dynamic library. When you use ld (the link-editor) or cc (the C compiler) to build a dynamic library, exceptions might not work and the global variables that are defined in the library are not initialized.
To build a dynamic (shared) library, you must create relocatable object files by compiling each object with the– Kpic or– KPIC option of CC. You can then build a dynamic library with these relocatable object files. If you get any bizarre link failures, you might have forgotten to compile some objects with– Kpic or– KPIC.
To build a C++ dynamic library named libfoo.so that contains objects from source files lsrc1.cc and lsrc2.cc, type:
% CC -G -o libfoo.so -h libfoo.so -Kpic lsrc1.cc lsrc2.cc |
The -G option specifies the construction of a dynamic library. The -o option specifies the file name for the library. The -h option specifies a name for the shared library. The -Kpic option specifies that the object files are to be position-independent.
The CC -G command does not pass any -l options to ld. If you want the shared library to have a dependency on another shared library, you must pass the necessary -l option on the command line. For example, if you want the shared library to be dependent upon libCrun.so, you must pass -lCr un on the command line.
Never use -Bsymbolic with programs containing C++ code, use linker map files instead. With -Bsymbolic, references in different modules can bind to different copies of what is supposed to be one global object.
The exception mechanism relies on comparing addresses. If you have two copies of something, their addresses won’t compare equal, and the exception mechanism can fail because the exception mechanism relies on comparing what are supposed to be unique addresses.
When shared libraries are opened using dlopen(), you must use RTLD_GLOBAL for exceptions to work.
When an organization builds a library for internal use only, the library can be built with options that are not advised for more general use. In particular, the library need not comply with the system’s application binary interface (ABI). For example, the library can be compiled with the -fast option to improve its performance on a known architecture. Likewise, it can be compiled with the -xregs=float option to improve performance.
When an organization builds a library for use by other organizations, the management of the libraries, platform generality, and other issues become significant. A simple test for whether or not a library is public is to ask if the application programmer can recompile the library easily. Public libraries should be built in conformance with the system’s application binary interface (ABI). In general, this means that any processor-specific options should be avoided. (For example, do not use– fast or– xtarget.)
The SPARC ABI reserves some registers exclusively for applications. For V7 and V8, these registers are %g2, %g3, and %g4. For V9, these registers are %g2 and %g3. Since most compilations are for applications, the C++ compiler, by default, uses these registers for scratch registers, improving program performance. However, use of these registers in a public library is generally not compliant with the SPARC ABI. When building a library for public use, compile all objects with the -xregs=no%appl option to ensure that the application registers are not used.
If you want to build a library that is written in C++ but that can be used with a C program, you must create a C API (application programming interface). To do this, make all the exported functions extern "C". Note that this can be done only for global functions and not for member functions.
If a C-interface library needs C++ run-time support and you are linking with cc, then you must also link your application with either libC (compatibility mode) or libCrun (standard mode) when you use the C-interface library. (If the C-interface library does not need C++ run-time support, then you do not have to link with libC or libCrun.) The steps for linking differ for archived and shared libraries.
When providing an archived C-interface library, you must provide instructions on how to use the library.
If the C-interface library was built with CC in standard mode (the default), add -lCrun to the cc command line when using the C-interface library.
If the C-interface library was built with CC in compatibility mode (-compat), add -lC to the cc command line when using the C-interface library.
When providing a shared C-interface library you must create a dependency on libC or libCrun at the time that you build the library. When the shared library has the correct dependency, you do not need to add -lC or -lCrun to the command line when you use the library.
If you are building the C-interface library in compatibility mode (-compat), add -lC to the CC command line when you build the library.
If you are building the C-interface library in standard mode (the default), add -lCrun to the CC command line when you build the library.
If you want to remove any dependency on the C++ runtime libraries, you should enforce the following coding rules in your library sources:
Do not use any form of new or delete unless you provide your own corresponding versions.
Do not use exceptions.
Do not use runtime type information (RTTI).
If you want to use dlopen() to open a C++ shared library from a C program, make sure that the shared library has a dependency on the appropriate C++ runtime (libC.so.5 for -compat=4, or libCrun.so.1 for -compat=5).
To do this, add -lC for -compat=4 or add -lCrun for -compat=5 to the command line when building the shared library. For example:
example% CC -G -compat=4... -lC example% CC -G -compat=5... -lCrun |
If the shared library uses exceptions and does not have a dependency on the C++ runtime library, your C program might behave erratically.
When shared libraries are opened with dlopen(), RTLD_GLOBAL must be used for exceptions to work.