Sun Studio 12 Update 1: C++ User's Guide

Part III Libraries

Chapter 12 Using Libraries

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.

12.1 The C 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.

12.2 Libraries Provided With the C++ Compiler

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

libCrun

C++ runtime 

–compat=5

libCstd

C++ standard library 

–compat=5

libiostream

Classic iostreams

–compat=5

libC

C++ runtime, classic iostreams

–compat=4

libcsunimath

Supports the -xia option

–compat=5

libcomplex

complex-number library 

–compat=4

librwtool

Tools.h++ 7

–compat=4,– compat=5

librwtool_dbg

Debug-enabled Tools.h++ 7

–compat=4,–compat=5

libgc

Garbage collection 

C interface 

libdemangle

Demangling 

C interface 


Note –

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.


12.2.1 C++ Library Descriptions

A brief description of each of these libraries follows.

If your compiler software is not installed in the /opt directory, ask your system administrator for the equivalent path on your system.

12.2.2 Accessing the C++ Library Man Pages

The man pages associated with the libraries described in this section are located in sections 1, 3, 3C++, and 3cc4.

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

12.2.3 Default C++ Libraries

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:

-lCstd -lCrun -lm -lc

In compatibility mode (-compat), the following libraries are linked by default:

-lC -lm -lc

See A.2.50 -library=l[,l...] for more information.

12.3 Related Library Options

The CC driver provides several options to help you use libraries.


example% CC test.cc -library=rwtools7,iostream

example% CC test.cc -library=gc -staticlib=gc

example% CC test.cc -compat=4 -staticlib=libC

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<install_directory>/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.

Programs built for deployment should be built with -norunpath or an -R option that that avoids looking in the compiler directory for libraries. (See 12.6 Using Shared Libraries).

12.4 Using Class Libraries

Generally, two steps are involved in using a class library:

  1. Include the appropriate header in your source code.

  2. Link your program with the object library.

12.4.1 The iostream Library

The C++ compiler provides two implementations of iostreams:

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.

12.4.2 The complex Library

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.

12.4.3 Linking C++ Libraries

The following table shows the compiler options for linking the C++ libraries. See A.2.50 -library=l[,l...] for more information.

Table 12–2 Compiler Options for Linking C++ Libraries

Library 

Compilation Mode 

Option  

Classic iostream

–compat=4

–compat=5

None needed 

-library=iostream

complex

–compat=4

-compat=5

-library=complex

None needed 

Tools.h++ version 7

–compat=4

–compat=5

-library=rwtools7

-library=rwtools7,iostream

-library=rwtools7_std

Tools.h++ version 7 debug

–compat=4

–compat=5

-library=rwtools7_dbg

-library=rwtools7_dbg,iostream

-library=rwtools7_std_dbg

Garbage collection

–compat=4

–compat=5

-library=gc

-library=gc

STLport version 4 

–compat=5

-library=stlport4

STLport version 4 debug 

–compat=5

-library=stlport4_dbg

12.5 Statically Linking Standard Libraries

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.


Note –

Linking the libCrun and libCstd statically is not recommended. The dynamic versions in /usr/lib are built to work with the version of Solaris where they are installed.


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.153 –xnolib for more information. See Linker and Libraries Guide for more information about ld.


Note –

Static versions of Solaris libraries in /lib and /usr/lib are no longer available. For example this attempt to link libc statically will fail:


      CC hello.cc -xnolib -lCrun -lCstd -Bstatic -lc 

12.6 Using Shared Libraries

The following C++ runtime shared libraries are shipped as part of the C++ compiler:

On Linux, these additional libraries are shipped as part of the C++ compiler:

On Solaris, those additional libraries, along with some others, are installed as part of the Solaris C++ runtime library package, SUNWlibC.

If your application uses any of the shared libraries that are shipped as part of the C++ compiler, the CC driver arranges for a runpath (refer to the -R option) pointing to the location of the library to be built into the executable. If the executable is later deployed to a different computer where the same compiler version is not installed in the same location, the required shared library will not be found.

At program start time, the library might not be found at all, or the wrong version of the library might be used, leading to incorrect program behavior. In such a case, you should ship the required libraries along with the executable, and build with a runpath that points to where they will be installed.

The article Using and Redistributing Sun Studio Libraries in an Applicationcontains a full discussion of this topic, along with examples and can be found at http://developers.sun.com/sunstudio/documentation/techart/stdlibdistr.html

12.7 Replacing the C++ Standard Library

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.

12.7.1 What Can Be Replaced

You can replace most of the standard library and its associated headers. The replaced library is libCstd, and the associated headers are the following:

<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.

12.7.2 What Cannot Be Replaced

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.

12.7.3 Installing the Replacement Library

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”.)

12.7.4 Using the Replacement Library

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.

12.7.5 Standard Header Implementation

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:

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.

12.7.5.1 Replacing Standard C++ Headers

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.

12.7.5.2 Replacing Standard C Headers

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:

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.

Caveats:

Chapter 13 Using The C++ Standard Library

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.

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.

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.

13.1 C++ Standard Library Header Files

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 

13.2 C++ Standard Library Man Pages

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 

13.3 STLport

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:

See A.2.50 -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:

13.3.1 Redistribution and Supported STLport Libraries

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 product documentation on the Sun Studio SDN portal at http://developers.sun.com/sunstudio/documentation/

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.

Chapter 14 Using the Classic iostream Library

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.

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

14.1 Predefined iostreams

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.

14.2 Basic Structure of iostream Interaction

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:

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.

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.

14.3 Using the Classic iostream Library

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

Header File 

Description  

iostream.h

Declares basic features of iostream library.

fstream.h

Declares iostreams and streambufs specialized to files. Includes iostream.h.

strstream.h

Declares iostreams and streambufs specialized to character arrays. Includes iostream.h.

iomanip.h

Declares manipulators: values you insert into or extract from iostreams to have different effects. Includes iostream.h.

stdiostream.h

(obsolete) Declares iostreams and streambufs specialized to use stdio FILEs.Includes iostream.h.

stream.h

(obsolete) Includes iostream.h, fstream.h, iomanip.h, and stdiostream.h. For compatibility with old-style streams from C++ version 1.2.

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.

14.3.1 Output Using iostream

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

14.3.1.1 Defining Your Own Insertion Operator

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.

14.3.1.2 Handling Output Errors

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.

14.3.1.3 Flushing

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).

14.3.1.4 Binary Output

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.

14.3.2 Input Using iostream

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.

14.3.3 Defining Your Own Extraction Operators

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:


Example 14–1 string Extraction Operator


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.

14.3.4 Using the char* Extractor

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.

14.3.5 Reading Any Single Character

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

Note –

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 ==’ ’);

14.3.6 Binary Input

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));

14.3.7 Peeking at Input

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;

14.3.8 Extracting Whitespace

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;

14.3.9 Handling Input Errors

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.

14.3.10 Using iostreams With stdio

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.

14.4 Creating iostreams

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.

14.4.1 Dealing With Files Using Class fstream

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:

14.4.1.1 Open Mode

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};

Note –

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);

14.4.1.2 Declaring an fstream Without Specifying a File

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);

14.4.1.3 Opening and Closing Files

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();
}

14.4.1.4 Opening a File Using a File Descriptor

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.

14.4.1.5 Repositioning Within a File

You can alter the reading and writing position in a file. Several tools are supplied for this purpose.


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.


Note –

Arbitrary seeks on text streams are not portable, but you can always return to a previously saved streampos value.


14.5 Assignment of iostreams

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.

14.6 Format Control

Format control is discussed in detail in the in the man page ios(3CC4).

14.7 Manipulators

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:

Table 14–2 iostream Predefined Manipulators

 

Predefined Manipulator  

Description  

ostr << dec, istr >> dec

Makes the integer conversion base 10.

ostr << endl

Inserts a newline character (’\n’) and invokes ostream::flush().

ostr << ends

Inserts a null (0) character. Useful when dealing with strstream.

ostr << flush

Invokes ostream::flush().

ostr << hex, istr >> hex

Makes the integer conversion base 16.

ostr << oct, istr >> oct

Make the integer conversion base 8.

istr >> ws

Extracts whitespace characters (skips whitespace) until a non-whitespace character is found (which is left in istr).

ostr << setbase(n), istr >> setbase(n)

Sets the conversion base to n (0, 8, 10, 16 only).

ostr << setw(n), istr >> setw(n)

Invokes ios::width(n). Sets the field width to n.

10 

ostr << resetiosflags(i), istr>> resetiosflags(i) 

Clears the flags bitvector according to the bits set in i.

11 

ostr << setiosflags(i), istr >> setiosflags(i)

Sets the flags bitvector according to the bits set in i.

12 

ostr << setfill(c), istr >> setfill(c)

Sets the fill character (for padding a field) to c.

13 

ostr << setprecision(n), istr >> setprecision(n)

Sets the floating-point precision to n digits.

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:

14.7.1 Using Plain Manipulators

A plain manipulator is a function that:

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;
}

14.7.2 Parameterized Manipulators

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:

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:

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);
   }

14.8 Strstreams: iostreams for Arrays

See the strstream(3CC4) man page.

14.9 Stdiobufs: iostreams for stdio Files

See the stdiobuf(3CC4) man page.

14.10 Streambufs

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.

14.10.1 Working With Streambufs

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 streambuf can have one or both of these pointers.

14.10.1.1 Position of 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.

14.10.2 Using Streambufs

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.

14.11 iostream Man Pages

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
Table 14–3 iostream Man Pages Overview

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: 

  • Member functions for class istream, which supports interpretation of characters fetched from a streambuf

  • Input formatting

  • Positioning functions described as part of class ostream.

  • Some related functions

  • Related manipulators

manip

Describes the input and output manipulators defined in the iostream library.

ostream

Details the following: 

  • Member functions for class ostream, which supports interpretation of characters written to a streambuf

  • Output formatting

  • Positioning functions described as part of class ostream

  • Some related functions

  • Related manipulators

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.

14.12 iostream Terminology

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  

Buffer

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.

Extraction

The process of taking input from an iostream.

Fstream

An input or output stream specialized for use with files. Refers specifically to a class derived from class iostream when printed in courier font.

Insertion

The process of sending output into an iostream.

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.

Stream

An iostream, fstream, strstream, or user-defined stream in general.

Streambuf

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.

Strstream

An iostream specialized for use with character arrays. It refers to the specific class when printed in courier font.

Chapter 15 Using the Complex Arithmetic Library

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.


Note –

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.


15.1 The Complex Library

The complex arithmetic library implements a complex number data type as a new data type and provides:

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.

15.1.1 Using the Complex Library

To use the complex library, include the header file complex.h in your program, and compile and link with the -library=complex option.

15.2 Type complex

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:


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.

15.2.1 Constructors of Class complex

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.

15.2.2 Arithmetic Operators

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:

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.

15.3 Mathematical Functions

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.


Note –

The implementation of the sqrt and atan2 functions is aligned with the C99 csqrt Annex G specification.


Table 15–1 Complex Arithmetic Library Functions

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

Complex Arithmetic Library Function

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. 

15.4 Error Handling

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:

  1. Set errno to zero before the operation.

  2. Test the operation.

The function complex_error takes a reference to type c_exception and is called by the following complex arithmetic library functions:

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.

15.5 Input and Output

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.

15.6 Mixed-Mode Arithmetic

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)

15.7 Efficiency

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.

15.8 Complex Man Pages

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 

Chapter 16 Building Libraries

This chapter explains how to build your own libraries.

16.1 Understanding 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:

However, dynamic libraries have some disadvantages:

16.2 Building Static (Archive) Libraries

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.


Note –

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.

16.3 Building Dynamic (Shared) Libraries

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 an internal 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 the linker, ld. To ensure proper initialization order, a shared library must have an explicit dependency on each other shared library it needs. To create the dependencies, use a -l option for each such library. Typical C++ shared libraries will use one of the following sets of options:


-lCstd -lCrun -lc     
-library=stlport4 -lCrun -lc     

To be sure you have listed all needed dependencies, build the library with the -zdefs option. The linker will issue an error message for each missing symbol definition. To provide the missing definitions, add a -l option for those libraries.

To find out if you have included unneeded dependencies, use the commands


ldd -u -r mylib.so     
ldd -U -r mylib.so

You can then rebuild mylib.so without the unneeded dependencies.

16.4 Building Shared Libraries That Contain Exceptions

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.

16.5 Building Libraries for Private Use

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.

16.6 Building Libraries for Public Use

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.

16.7 Building a Library That Has a C API

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.

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 want to remove any dependency on the C++ runtime libraries, you should enforce the following coding rules in your library sources:

16.8 Using dlopen to Access a C++ Library From a C Program

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.