United States

Compaq C++

# Compaq C++
Using Compaq C++ for OpenVMS VAX

Previous | Contents | Index

# Chapter 7
The C++ Standard Library

Compaq C++ currently provides a partial implementation of the C++ Standard Library. The ANSI X3/J16 C++ committee is in the process of standardizing the C++ Standard Library, and when this process is complete Compaq C++ will provide a complete library implementation. In the meantime, the subset provided has been selected from among the most stable parts of the library as defined in the ANSI C++ draft.

This release of Compaq C++ contains the following components of the C++ Standard Library:

- Standard Template Library (STL)
- String Library
- Numeric Limits class
- Auto_ptr class
- Standard exception classes
- Complex Math Library
- Allocator class

Some of the components in the C++ Standard Library are designed to replace nonstandard components that are currently distributed in the Compaq C++ Class Library. Compaq will continue to provide the Compaq C++ Class Library in its nonstandard form. However you now have the option of using the new standard components.

The following sections provide more information on the Compaq C++ implementation of the Standard Library, including upward compatibility, compiling and linking, thread safety, and details on each component of the library.

# 7.1 Important Compatibility Information

Because the standardization process for the C++ Standard Library is not yet completed, Compaq cannot guarantee that this version of the library is compatible with any past or future releases. We ship the run-time portion of the library in object form, not in shareable form, to emphasize this situation.

Therefore, Compaq recommends that you do not use this library for any production code that requires upward compatibility. This release of the library matches as closely as is feasible the standard described in the post-Stockholm ANSI C++ draft dated 24 September 1996.

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

To build programs that use the C++ Standard Library, certain changes to the Compaq C++ compiler and linker commands are necessary.

Compiler Command Changes

The `cxx` command line must include the following qualifier:

    /assume=noheader_type_default

This qualifier is required because Standard Library header files do not have file name extensions, and Compaq C++ by default appends a file name extension to such header file names (for backward compatibility). The `/assume=noheader_type_default` qualifier instructs Compaq C++ to not append a file extension.

You do not need to specify the `/template=auto` qualifier on the command line because the Compaq C++ compiler performs automatic template instantiation by default.

Linker Command Changes

To link a program that uses the C++ Standard Library, you must use the `cxxlink` command in place of the `link` command. The `cxxlink` command continues the automatic template instantiation process, includes the Standard Library run-time support ( `SYS$LIBRARY:LIBCXXSTD.OLB` ) at link time, and creates the final image.

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

    cxx/assume=noheader_type_default prog.cxx
    cxxlink prog.obj

Thread Safety

The C++ Standard Library is thread safe, meaning that all internal library data is protected against simultaneous access from multiple threads.

# 7.3 Incompatibilities Between the Standard Library and the ANSI C++ Draft

Compaq C++ currently does not support all the necessary language features to compile a Standard Library that meets the specifications of the September ANSI C++ draft. Therefore, where possible, Compaq's implementation of the Standard Library contains workarounds for these missing language features.

The following list shows the unsupported ANSI C++ language features and their workarounds in the Compaq C++ Standard Library:

- Namespaces
  The Standard Library classes and functions are not placed in `namespace std` .
- Member function templates
  Some member function templates within the Standard Library have been substituted with member functions for a given type.
- Bool
  The current STL simulates bool as a `typedef` of `int` . Thus, the Compaq C++ STL cannot supply the specialization `vector<bool>` because it would conflict with `vector<int>` . In the interim, Compaq supplies a `bit_vector` class in place of `vector<bool>` .
- Wide characters
  The Compaq C++ compiler does not support `wchar_t` as a built-in type, therefore the current String Library does not support wide character types.
- The Compaq C++ Numeric Limits class does not provide a specialization for bool or for wchar_t because Compaq C++ does not treat them as built-in types.
- Mutable
  Compaq C++ does not support the `mutable` keyword, thus the `auto_ptr release()` member is not declared `const` .

The following data structures and algorithms supplied with the current STL differ from those specified in the September 1996 ANSI C++ draft:

- Because Compaq C++ does not supply a new standard stream class, `streambuf_iterators` are not implemented. Note that `stream_iterators` are supplied.
- Because the allocator from the latest ANSI C++ draft requires member templates, which Compaq C++ does not support, two versions of the allocator are provided: one that is standard-conforming and an alternative that does not rely on member templates. See Section 7.10 for more details.

Additionally, the following are some minor incompatibilities in the current String Library that correct what Compaq believes are mistakes in the draft:

- The Compaq C++ extraction operator clears the string before extraction.
- The Compaq C++ extraction operator skips white space before extraction.
- The Compaq C++ `getline()` function does not "end by storing the count in is." To do this may not be feasible.
- The Compaq C++ `insert()` and `replace()` functions are different from the draft. For example, the second `insert()` function does not have any default arguments and, on return, the first `insert()` function performs an `insert(pos1,str,0,npos)` . A similar modification was made to the `replace()` function.

# 7.4 Standard Template Library

Compaq C++ provides an implementation of the Standard Template Library (STL).

The following sections provide information specific to the Compaq C++ implementation of the STL. For information on how to program with the STL, refer to the STL Tutorial and Reference Guide that is part of the Compaq C++ printed documentation set. See Section 7.4.3 for differences between the STL Tutorial and Reference Guide and the Compaq C++ implementation of the STL.

## 7.4.1 Examples of Use

The following are some simple examples of using the containers and algorithms in the STL. You should compile and link these examples with the commands:

    cxx/assume=noheader_type_default prog.cxx
    cxxlink prog

For details on how to build programs that use the STL, see Section 7.2.

Using the vector class

    // This example shows how to create a vector,
    // initialize it with values, sort and print it

    #include <vector>
    #include <algorithm>
    #include <iostream.hxx>

    int main() {

         // create a vector of 4 ints
         vector<int> v(4);

         // initialize the vector with values
         v[0]=2;
         v[1]=0;
         v[2]=3;
         v[3]=1;

         // sort the vector
         sort(v.begin(),v.end());

         // print the sorted vector
         for (vector<int>::iterator viter=v.begin();viter!=v.end();viter++)
             cout << *viter << " ";
         cout << endl;

            return 0;
    }

Using the list class

    // This example shows how to create a list, initialize
    // it with values, find a particular value and print
    // the element before and after that value

    #include <list>
    #include <iostream.hxx>
    #include <string>

    int main() {

         // create a list
         list<string> l;

         // add some values to the list
         l.insert(l.end(),"Stepanov");
         l.insert(l.end(),"Koenig");
         l.insert(l.end(),"Stroustrup");
         l.insert(l.end(),"Lippman");

         // find the value "Stroustrup"
         string value("Stroustrup");
         list<string>::iterator liter=find(l.begin(),l.end(), value);

         // print out the value before and after "Stroustrup"
         if (liter!=l.end())
               cout << "Stroustrup was found after " << *(--liter)
               << " and before " << *(++(++liter)) << endl;

         return 0;
    }

Using the map class

    // This example shows how to create a map,
    // add some values, and find the number of elements
    // which match a specified criterion

    #include <map>
    #include <iostream.hxx>

    bool smaller (pair<const char* const, float> p)
    {
    // returns true if element costs less than $3.00
            return p.second < 3.00;
    }

    int main() {

         // create a map
         map<const char*,float, less<const char*> > shopmap;

         // add some elements to the map
         shopmap["milk"]=1.29;
         shopmap["steak"]=5.99;
         shopmap["cornflakes"]=2.69;
         shopmap["cheese"]=3.42;
         shopmap["ricekrispies"]=2.25;

         // count the number of items less than $3.00
         int num_items = 0;
         count_if(shopmap.begin(),shopmap.end(),smaller,num_items);

         // print the results
         cout << "number of items less than 3 dollars is: " << num_items << endl;

         return 0;
    }

## 7.4.2 Upgrading from the Nonstandard Compaq C++ Class Library

The following discussion guides you through upgrading Compaq C++ Class Library code to use the STL, specifically replacing the vector and stack classes that are currently in the `vector.hxx` header file.

### 7.4.2.1 Upgrading from the Compaq C++ Class Library Vector to the STL Vector

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

- Change the name of your `#include` statement from `<vector.h>` or `<vector.hxx>` to `<vector>` .
- Remove the `vectordeclare` and `vectorimplement` declarations from your code.
- Change all `vector(type)` declarations to `vector<type>` . For example, `vector(int) vi` should become `vector<int> vi` .
- Note that the following member functions are replaced in the STL library:

  Nonstandard Vector Function | Replaced with STL Vector Function
  --- | ---
  `elem(int index)` | `operator[](size_t index)` (no bounds checking)
  `operator[](int index)` | `at(size_t index)` (bounds checking)
  `setsize(int newsize)` | `resize(size_t newsize)`

- When copying vectors of unequal lengths, note that the STL vector has a different behavior as follows:
  When using the STL vector, if the target vector is smaller than the source vector, the target vector automatically increases to accommodate the additional elements.
  The Compaq C++ Class Library vector displays an error and aborts when this situation occurs.
- Note that another difference in behavior occurs when you specify a negative index for a vector.
  The nonstandard Compaq C++ vector class detects the negative specification and issues an error message. However, the STL vector silently converts the negative value to a large positive value, because indices are represented as type `size_t (unsigned long)` rather than `int` .
- When an out-of-bounds error occurs, the nonstandard Compaq C++ vector class prints an error message and aborts, whereas the STL vector throws an out-of-range object.

### 7.4.2.2 Upgrading from the Compaq C++ Class Library Stack to the STL Stack

To change your code from using the nonstandard Compaq C++ stack to the STL stack, consider the following actions:

- Change the name of your `#include` statement from `<vector.h>` or `<vector.hxx>` to `<stack>` .
- Remove the `stackdeclare` and `stackimplement` declarations from your code.
- Change all `stack(type)` declarations to `stack<type, deque<type> >` . For example, `stack(int) si` should become `stack<int, deque<int> > si` .
- Do not specify an initial size for an STL stack. The stack must start out empty and grow dynamically (as you push and pop).
- The following member functions are not supported or have different semantics:

  Nonstandard Stack | STL Stack
  --- | ---
  `size_used()` | Does not exist because the `size()` function always is equal to the `size_used()` function.
  `full()` | Does not exist because the stack always is full.
  `pop()` | Does not return the popped element. To simulate nonstandard stack behavior, first get the element as the return type from the `top()` function and then call the `pop()` function. For example, change: `int i=s.pop();` to the following:
      int i=s.top();

      s.pop();

- The STL stack differs from the Compaq C++ Class Library stack in the way errors are detected. Unlike the nonstandard stack, you cannot overflow an STL stack because space is allocated dynamically as you push elements onto the stack. And if you underflow an STL stack, you will get a core dump instead of an error message.

## 7.4.3 Differences Between STL Tutorial and Reference Guide and the Compaq C++ STL

The STL Tutorial and Reference Guide (the Guide) is based on the STL implementation provided by the Hewlett-Packard Company. Because the Compaq C++ STL incorporates changes from the ANSI C++ draft, the two implementations differ slightly. Differences also exist because the Compaq C++ compiler does not currently support all of the new language features specified in the ANSI C++ draft; refer to Section 7.3 for the list of missing language features. This section discusses the remaining differences.

### 7.4.3.1 Header File Names

The header file names shown in the STL Tutorial and Reference Guide differ from the Compaq C++ header file names, as shown in the following table:

Names Used in the Guide | Names Supplied by Compaq C++
--- | ---
`algo.h` | Divided into `algorithm` and `numeric`
`deque.h` | `deque`
`function.h` | `functional`
`iterator.h` | `iterator`
`list.h` | `list`
`multiset.h` | `set`
`map.h` | `map`
`multimap.h` | `map`
`set.h` | `set`
`stack.h` | Divided into `stack` and `queue`
`vector.h` | `vector`

### 7.4.3.2 STL Run-Time Support

The STL Tutorial and Reference Guide states that you need to compile the run-time `.cpp` files that are provided with the Hewlett-Packard implementation, such as `random.cpp` and `tempbuf.cpp` .

Compaq C++ already provides this run-time support in an object library and automatically links this library into your application; therefore, you can ignore the Guide's comments about compiling this support.

### 7.4.3.3 Guide Examples Need to Be Modified

The STL Tutorial and Reference Guide contains many example programs. Appendix B of the Guide shows a World Wide Web address (active as of this printing) from which you can copy these example programs. Because of the differences outlined in the previous sections, these example programs must be modified to work with the Compaq C++ STL. To perform the necessary modifications, Compaq C++ provides the following procedure:

    sys$common:[syshlp.examples.cxx]update_stl_book_examples.com

Before running this procedure, copy and prepare the example programs. Use the following steps as guidance:

1. Determine whether the `unzip` facility is available on your system. If not, you can copy it from the following location:
   For OpenVMS VAX:

       ftp://ftp.digital.com/pub/VMS/unzip-vax.exe

   For OpenVMS Alpha:

       ftp://ftp.digital.com/pub/VMS/unzip-axp.exe

2. Copy the following example programs from the World Wide Web address `http://www.aw.com/cp/musser-saini.html` , specified in the Guide:
   - `diction.zip`
   - `examples.zip`
3. Unzip the files into a directory. To use the unzip image that you copied in step 1, you need to define a foreign command symbol. Assuming the unzip image is in your login directory, you would use the following commands:
   For OpenVMS VAX:

       $ unzip :==  $sys$login:unzip-vax.exe
       $ unzip diction.zip
       $ unzip examples.zip

   For OpenVMS Alpha:

       $ unzip :==  $sys$login:unzip-axp.exe
       $ unzip diction.zip
       $ unzip examples.zip

4. Change your current working directory to the directory where the example programs exist, and execute the procedure to modify the files as follows:

       $ @sys$common:[syshlp.examples.cxx]update_stl_book_examples.com

Now that your example programs are ready, compile and link them with the following commands:

    $ cxx/exception/template_define/assume=(noheader_type_default,-
      writable_string_literals) ex.cpp
    $ cxxlink ex.obj

To link `ex17-01` , you must compile `screen.cpp` and `shape.cpp` and link with the resulting object files.

Note The header file, `bstring.h` , which is included with the example programs, is based on the string library as defined by an old version of the ANSI C++ draft. Compaq recommends that you do not use this header file and instead use the <string> header provided by Compaq C++.

### 7.4.3.4 Differences by Chapter

This section describes functional differences between the Compaq C++ STL and the STL Tutorial and Reference Guide by chapter.

Chapter 6

- The Guide does not discuss the specialization of `vector, vector<bool>` , which is in the ANSI C++ draft. See Section 7.3 for information about how the Compaq C++ implementation handles the lack of a bool built-in type.
- The Compaq C++ STL supplies an `assign()` function, in addition to the `assign()` function specified in §6.1.7 of the Guide, with the following signature:

      assign(size_type position, const T& value)

  This function assigns the value to the element at the position specified in the argument.

Chapter 18

The Compaq C++ STL description of the `reverse_iterator` type definition differs from the description in §18.9 of the Guide as follows:

- The Compaq C++ STL type definition of `self` has an extra `Pointer` argument as defined in the latest ANSI C++ draft:

      typedef reverse_iterator<RandomAccessIterator, T, Reference,
      Pointer, Distance> self;

- This extra `Pointer` argument also occurs in the Compaq C++ STL global functions: `operator-` , `operator+` , `operator==` , and `operator<` .
- The Compaq C++ STL provides an additional member function: `operator->` .

Chapter 19

- Besides the member functions listed in §19.1.2 of the Guide, the Compaq C++ STL provides the following member function:

      a.clear()

  This function erases all elements in the container.
- Besides the member functions listed in §19.1.3 of the Guide, the Compaq C++ STL provides the following member functions:

      a.assign(q1, q2)

  This function erases all the elements in the container and then inserts all elements in the range `(q1, q2)` .

      a.assign(n, t)

  This function erases `a[n]` and inserts `t` at `a[n]` .

Chapter 20

- The Compaq C++ STL implementation of the `for_each()` function has a return type of `Function` and returns `f` .
- The Compaq C++ STL implementation of the `rotate_copy()` function has a return type of `OutputIterator` and returns the past-the-end iterator, `result + last - first` .

Chapter 22

- The Guide does not mention where `allocator` is declared. The Compaq C++ STL places the declaration of `allocator` in the `<memory>` header.
- See Section 7.3 for a description of how to customize allocators using the Compaq C++ STL implementation.

See also Section 7.5.5 for differences between the Guide string class and the Compaq C++ Standard String Library.

## 7.4.4 Optional Switch to Control Buffering

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

- Preallocate 16K bytes of space on the stack
- Allocate the required amount of storage dynamically

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

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

    /define=__DEC_DYN_ALLOC

# 7.5 The basic_string Library

Compaq C++ provides an implementation of the basic_string Library that consists of the basic_string template class, with parameters for the following:

- Character type
- Character traits type (specified by the template class, string_char_traits)
- Allocator type

Note This manual refers to the new standard String class implementation in Compaq C++ as the basic_string Library. This is in contrast with an earlier (still maintained) implementation known as the String Package.

The basic_string Library also declares a `string` typedef to represent the typical usage, which is a string of normal (skinny) characters. For example:

    #include <string>

    string str("abc"); // create a string containing "abc"
    str.append('d');   // str now contains "abcd"
    cout << s << endl; // print str to cout

The wide character typedef ( `wstring` ) is not yet supported.

## 7.5.1 The basic_string Member Functions

The basic_string class can be used as character text, as an array of characters, or as an STL-like sequence of characters. The string member functions described below support these alternative uses.

### 7.5.1.1 Constructors/Destructors/Assignment

> ### basic_string(const Allocator& a = Allocator());

> Constructs an empty string.

> ### basic_string(const basic_string& str, size_type pos = 0, size_type n = npos, const Allocator& a = Allocator());

> Constructs a string by copying all elements from str, starting at position pos in str and ending at position pos + n.

> ### basic_string(const charT* s,size_type n,const Allocator& a = Allocator());

> ### basic_string(const charT* s, const Allocator& a = Allocator());

> Constructs a string from s. If n is supplied it only copies the first n characters from s.

> ### basic_string(size_type n, charT c, const Allocator& a = Allocator());

> Constructs a string with n copies of c, that is: `string(4,'a')` would construct a string of `aaaa` .

> ### basic_string(iterator begin, iterator end, const Allocator& a = Allocator());

> Constructs a string from the characters between begin and end.

> ### ~basic_string();

> Destroys the string and frees all associated memory.

> ### basic_string& operator=(const basic_string& str);
> basic_string& operator=(const charT* s);

> ### basic_string& operator=(charT c);

> Assigns str, `s` or c to the current string.

### 7.5.1.2 Capacity

> ### size_type size() const;

> ### size_type length() const;

> Returns a count of the number of characters in the string.

> ### size_type max_size() const;

> Specifies the maximum number of elements that can be in the string, usually limited by the amount of available memory.

> ### void resize(size_type n);

> If n is less than the current value of `size()` , `resize()` truncates the string to length n. If n is greater than the current value of `size()` , `resize()` expands the string to length n and pads the string with null characters.

> ### void resize(size_type n, charT c);

> If n is less than the current value of `size()` , `resize()` truncates the string to length n. If n is greater than the current value of `size()` , `resize()` expands the string to length n and pads the string with c characters.

> ### size_type capacity() const;

> Returns the number of elements allocated in the string.

> ### void reserve(size_type res_arg);

> Reallocates the string if the current capacity is less than res_arg. Invalidates all iterators, pointers and references to the string.

> ### bool empty() const;

> Returns true if length is zero, otherwise returns false.

### 7.5.1.3 Element access

> ### charT operator[](size_type pos) const;
> reference operator[](size_type pos);

> ### charT at(size_type pos) const;
> reference at(size_type pos);

> The subscript operator returns the character at position pos in the string. The `at()` function is similar except it throws an out-of-range exception if pos is invalid, that is, if it is greater than the current length of the string.

### 7.5.1.4 Modifiers

> ### basic_string& operator+=(const basic_string& str);
> basic_string& operator+=(const charT* s); basic_string& operator+=(charT c);

> ### basic_string& append(const basic_string& str);
> basic_string& append(const charT* s);

> Appends str, s or c to the string and returns `*this` .

> ### basic_string& append(const basic_string& str,size_type pos,size_type n);

> Appends a string constructed by copying all elements from str onto the string, starting at position pos in str and ending at position pos + n. Returns `*this` .

> ### basic_string& append(const charT* s, size_type n);

> Appends onto the string the string created from the first n characters of s. Returns `*this` .

> ### basic_string& append(size_type n, charT c);

> Appends onto the string n number of the value of c. Returns `*this` .

> ### basic_string& append(iterator first, iterator last);

> Appends onto the current string the string constructed from the elements in the range first to last. Returns `*this` .

> ### basic_string& assign(const basic_string& str);

> ### basic_string& assign(const charT* s);

> Assigns str or s to the current string. Returns `*this` .

> ### basic_string& assign(const basic_string& str,size_type pos, size_type n);

> Assigns a string constructed by copying onto the current string all elements from str, starting at position pos in str and ending at position pos + n Returns `*this` .

> ### basic_string& assign(const charT* s, size_type n);

> Assigns the string created from the first n characters of s to the current string. Returns `*this` .

> ### basic_string& assign(size_type n, charT c);

> Assigns n number of values of c to the string. Returns `*this` .

> ### basic_string& assign(iterator first, iterator last);

> Assigns the string constructed from the elements in in the range first to last. Returns `*this` .

> ### basic_string& insert(size_type pos1, const basic_string& str);

> Inserts str into the string after position pos1. Returns `*this` . If pos1 is greater than the size of the string, this function throws a length-error exception. Returns `*this` .

> ### basic_string& insert(size_type pos1, const basic_string& str, size_type pos2, size_type n);

> Inserts into the string after position pos1 the elements of str beginning at position pos2 and ending at either pos2+n or the end of str (whichever is smallest). If pos1 is greater than the size of the string or pos2 is greater than the size of str, this function throws a length-error exception. Returns `*this` .

> ### basic_string& insert(size_type pos,const charT* s);

> Inserts the character string s into the string beginning after position pos. Returns `*this` .

> ### basic_string& insert(size_type pos, const charT* s, size_type n);

> Inserts the first n characters of the character string s into the string after position pos. Returns `*this` .

> ### basic_string& insert(size_type pos, size_type n, charT c);

> Inserts n copies of the character c into the string after position pos. Returns `*this` .

> ### iterator insert(iterator p, charT c);

> Inserts the character c into the string before the character referred to by p and returns an iterator pointing at the element immediately following p prior to the element being inserted.

> ### void insert(iterator p, size_type n, charT c);

> Inserts the n copies of the character c into the string before the character referred to by p.

> ### void insert(iterator p, iterator first, iterator last);

> Inserts before the character referred to by p the characters in the string from first up to but not including last

> ### basic_string& erase(size_type pos = 0, size_type n = npos);

> Erases from the string the characters beginning at position pos and ending at position n. Returns `*this` .

> ### iterator erase(iterator pos);

> Erases the character in the string at pos and returns an iterator pointing at the element immediately following p prior to the element being erased.

> ### iterator erase(iterator first, iterator last);

> Erases the characters in the string from first up to but not including last and returns an iterator pointing at the element immediately following last prior to the element being erased.

> ### basic_string& replace(size_type pos1, size_type n1, const basic_string& str);

> Removes the characters in the string from pos1 to pos1+n1 or to the end of the string (whichever is smaller). Inserts str into the string at pos1. Returns `*this` . If pos1 is greater than the size of the string, this function throws an out-of-range exception.

> ### basic_string& replace(size_type pos1,size_type n1, const basic_string& str,size_type pos2,size_type n);

> Removes the characters in the string from pos1 to pos1+n1 or to the end of the string (whichever is smaller). Inserts the string created by using the characters in str from pos2 to pos2+n or the end of str (whichever is less) into the string at pos1. Returns `*this` . If pos1 is greater than the size of the string or pos2 is greater than str, this function throws an out-of-range exception. If the `size()` of the string minus the size of the string to be removed is greater than the npos minus the size of the string to be inserted, this function throws an length-error exception.

> ### basic_string& replace(size_type pos1,size_type n1,const charT* s);

> Removes the characters in the string from pos1 to pos1+n1 or to the end of the string (whichever is smaller). Inserts s into the string at pos1. Returns `*this` . If pos1 is greater than the size of the string, this function throws an out-of-range exception.

> ### basic_string& replace(size_type pos1,size_type n1,const charT* s,size_type n2);

> Removes the characters in the string from pos1 to pos1+n1 or to the end of the string (whichever is smaller). Inserts the string created by copying the first n2 characters of s into the string at pos1. Returns `*this` . If pos1 is greater than the size of the string, this function throws an out-of-range exception.

> ### basic_string& replace(size_type pos1,size_type n1,size_type n2,charT c);

> Removes the characters in the string from pos1 to pos1+n1 or to the end of the string (whichever is smaller). Inserts the string created by copying the first n2 characters of the character c into the string at pos1. Returns `*this` . If pos1 is greater than the size of the string, this function throws an out-of-range exception.

> ### basic_string& replace(iterator i1, iterator i2, const basic_string& str);

> Removes the characters in the range i1 to i2 and inserts str at i1. Returns `*this` .

> ### basic_string& replace(iterator i1, iterator i2, const charT* s);

> Removes the characters in the range i1 to i2 and inserts s at i1. Returns `*this` .

> ### basic_string& replace(iterator i1, iterator i2, const charT* s, size_type n);

> Removes the characters in the range i1 to i2 and inserts n characters of s at i1. Returns `*this` .

> ### basic_string& replace(iterator i1, iterator i2, size_type n, charT c);

> Removes the characters in the range i1 to i2 and inserts n copies of the character c at i1. Returns `*this` .

> ### basic_string& replace(iterator i1, iterator i2, iterator i3, iterator i4);

> Removes the characters in the range i1 to i2 and inserts the characters in the range i3 to i4. Returns `*this` .

> ### size_type copy(charT* s, size_type n, size_type pos = 0) const;

> Replaces s with the elements from the string beginning at position pos and ending at either pos+n or the end of the string (whichever is smaller). If pos is greater than the value of `size()` , this function throws an out-of-range exception. It returns the size of the new string s. Before calling the `copy()` function, s must have already been allocated to have as least as many elements as needed to hold the results of the copy.

> ### void swap(basic_string<charT,traits,Allocator>& s);

> Swaps the contents (that is, the data members) of s and `*this` .

### 7.5.1.5 Operations

> ### const charT* c_str() const;

> ### const charT* data() const;

> Returns a pointer to the `char*` representation of the string.

> ### const allocator_type& get_allocator() const;

> Returns a reference to the string's allocator object.

> ### size_type find(const basic_string& str, size_type pos = 0) const;

> Returns the lowest position at which str is embedded in the string starting at position pos in the string, if no such position exists, the function returns npos.

> ### size_type find(const charT* s, size_type pos = 0) const;

> Returns the lowest position at which s is embedded in the string starting at position pos in the string, if no such position exists, the function returns npos.

> ### size_type find(charT c, size_type pos = 0) const;

> Returns the lowest position at which c is embedded in the string starting at position pos in the string, if no such position exists, the function returns npos.

> ### size_type find(const charT* s, size_type pos, size_type n) const;

> Returns the lowest position at which the first n characters of s are embedded in the string starting at position pos in the string, if no such position exists, the function returns npos.

> The function `rfind()` is similar to the `find()` function except that it returns the highest position in the string.

> ### size_type find_first_of(const basic_string<charT, traits, Allocator>& str, size_type pos = npos);

> Returns the first position in the string that one of the characters contained in the argument str matches. For example:

>      string s = "abcdef";
>      size_t index = s.find_first_of("cehb"); // index of 'b' is 2

> If the pos argument is supplied, no character in the string beyond position pos will be considered.

> ### size_type find_first_of(const charT* s, size_type pos = npos);

> Calls the `find_first_of()` function (described above) constructing the str argument from s.

> ### size_type find_first_of(const charT* s, size_type pos, size_type n);

> Calls the `find_first_of()` function (described above) constructing the str argument from the first n characters of s.

> ### size_type find_first_of(charT c, size_type pos = npos);

> Calls the `find_first_of()` function (described above) constructing the str argument from the character c.

> ### size_type find_last_of(const basic_string<charT, traits, Allocator>& str, size_type pos = npos);

> Returns the last position in the string that one of the characters contained in the argument str matches. For example:

>      string s = "abcdef";
>      size_t index = s.find_last_of("cehb"); // index of 'e' is 4

> If the pos argument is supplied, no character in the string beyond position pos will be considered.

> ### size_type find_last_of(const charT* s, size_type pos = npos);

> Calls the `find_last_of()` function (described above) constructing the str argument from s.

> ### size_type find_last_of(const charT* s, size_type pos, size_type n);

> Calls the `find_last_of()` function (described above) constructing the str argument from the first n characters of s.

> ### size_type find_last_of(charT c, size_type pos = npos);

> Calls the `find_last_of()` function (described above) constructing the str argument from the character c.

> The find_first_not_of() and find_last_not_of() functions are similar to the functions described above except that they return the first (or last) position of one of the characters NOT in the string. For example:

>      string s = "abcdef";
>      size_t index = s.find_last_not_of("cfehb"); // index of 'd' is 4
>      index = s.find_first_not_of("cda"); // index of 'b' is 2

> ### basic_string substr(size_type pos = 0, size_type n = npos) const;

> Returns the substring starting at pos of length n. If pos is greater than the current size of the string, this function throws an out-of-range exception.

> ### int compare(const basic_string& str);

> Compares each corresponding character starting at the beginning of the string and str. The number of elements used for the comparison is the smaller of the size of str or the size of the string. If the character in the string is less than the corresponding character in str, a negative value is returned. If the character in the string is greater than the corresponding character in str, a positive value is returned. If all of the elements are equal a negative value is returned if the value of the size of the string is less than the size of str, 0 if they are equal, and a positive value of the size of the string is greater than the size of str.

> ### int compare(charT* s) const;

> Calls the `compare()` function (described above) by constructing the string str out of s.

> ### int compare(size_type pos, size_type n1, charT* s,size_type n2 = npos);

> Calls the `compare()` function (described above). The string to compare is created from the first n1 elements of the string beginning at position pos and the argument str is created from the first n2 elements of s.

> ### int compare(size_type pos, size_type n1, const basic_string& str);

> Calls the `compare()` function (described above). The string to compare is created from the first n1 elements of the string beginning at position pos and is compared to str.

> ### int compare(size_type pos, size_type n1, const basic_string& str, size_type pos2, size_type n2);

> Calls the `compare()` function (described above). The string to compare is created from the first n1 elements of the string beginning at position pos and the argument str is created from the first n2 elements of str beginning at position pos2.

### 7.5.1.6 Iterators

> ### iterator begin();
> const_iterator begin() const;

> ### iterator rbegin();
> const_iterator rbegin() const;

> Returns a random access iterator. Dereferencing the return value will give the character at the beginning of the string. The iterator returned by the `begin()` function will move forward through the string with operator++, and the `rbegin()` will move forward through the string with operator -- .

> ### iterator end();
> const_iterator end() const;

> ### iterator rend();
> const_iterator rend() const;

> Returns a random access iterator to one-past the end of the string. Dereferencing the return value--1 will give the character at the end of the string. The iterator returned by the `end()` function will move backward through the string with operator -- , and the `rend()` will move backward through the string with operator++.

> The following is an example of a simple use of iterators:

>     #include <string>

>     string str("azbzc");
>     int count = 0; // count the number of z's
>     for (string::iterator iter = str.begin(); iter!= str.end(); iter++)
>      if ((*(iter)=='z') count++;

## 7.5.2 The basic_string Nonmember Functions

operator+

The following `operator+` functions return the string constructed from adding the character or characters in lhs to the character or characters in rhs:

    template <class charT, class traits, class Allocator>
    basic_string<charT, traits, Allocator> operator+(
            const basic_string<charT, traits, Allocator>& lhs,
            const basic_string<charT, traits, Allocator>& rhs);
    template <class charT, class traits, class Allocator>
    basic_string<charT, traits, Allocator> operator+(const charT* lhs,
            const basic_string<charT, traits, Allocator>& rhs);
    template <class charT, class traits, class Allocator>
    basic_string<charT, traits, Allocator> operator+(
            const basic_string<charT, traits, Allocator>& lhs,
            const charT* rhs);
    template <class charT, class traits, class Allocator>
    basic_string<charT, traits, Allocator> operator+(const charT lhs,
            const basic_string<charT, traits, Allocator>& rhs);
    template <class charT, class traits, class Allocator>
    basic_string<charT, traits, Allocator> operator+(
            const basic_string<charT, traits, Allocator>& lhs,
            const charT rhs);

Relational Operators

The following `operator==` functions return a value of TRUE if lhs == rhs, where lhs and rhs are converted into strings if necessary; otherwise, the following return a value of FALSE:

    template <class charT, class traits, class Allocator>
    bool operator==(
            const basic_string<charT, traits, Allocator>& lhs,
            const basic_string<charT, traits, Allocator>& rhs);
    template <class charT, class traits, class Allocator>
    bool operator==(const charT* lhs,
            const basic_string<charT, traits, Allocator>& rhs);
    template <class charT, class traits, class Allocator>
    bool operator==(
            const basic_string<charT, traits, Allocator>& lhs,
            const charT* rhs);

The following `operator!=` functions return a value of TRUE if lhs != rhs, where lhs and rhs are converted into strings if necessary; otherwise, the following return a value of FALSE:

    template <class charT, class traits, class Allocator>
    bool operator!=(
            const basic_string<charT, traits, Allocator>& lhs,
            const basic_string<charT, traits, Allocator>& rhs);
    template <class charT, class traits, class Allocator>
    bool operator!=(const charT* lhs,
            const basic_string<charT, traits, Allocator>& rhs);
    template <class charT, class traits, class Allocator>
    bool operator!=(
            const basic_string<charT, traits, Allocator>& lhs,
            const charT* rhs);

The following `operator<` functions return a value of TRUE if lhs < rhs, where lhs and rhs are converted into strings if necessary; otherwise, the following return a value of FALSE:

    template <class charT, class traits, class Allocator>
    basic_string<charT, traits, Allocator> operator<(
            const basic_string<charT, traits, Allocator>& lhs,
            const basic_string<charT, traits, Allocator>& rhs);
    template <class charT, class traits, class Allocator>
    basic_string<charT, traits, Allocator> operator<(const charT* lhs,
            const basic_string<charT, traits, Allocator>& rhs);
    template <class charT, class traits, class Allocator>
    basic_string<charT, traits, Allocator> operator<(
            const basic_string<charT, traits, Allocator>& lhs,
            const charT* rhs);

The following `operator>` functions return a value of TRUE if lhs > rhs, where lhs and rhs are converted into strings if necessary; otherwise, the following return a value of FALSE:

    template <class charT, class traits, class Allocator>
    basic_string<charT, traits, Allocator> operator>(
            const basic_string<charT, traits, Allocator>& lhs,
            const basic_string<charT, traits, Allocator>& rhs);
    template <class charT, class traits, class Allocator>
    basic_string<charT, traits, Allocator> operator>(const charT* lhs,
            const basic_string<charT, traits, Allocator>& rhs);
    template <class charT, class traits, class Allocator>
    basic_string<charT, traits, Allocator> operator>(
            const basic_string<charT, traits, Allocator>& lhs,
            const charT* rhs);

The following `operator<=` functions return a value of TRUE if lhs <= rhs, where lhs and rhs are converted into strings if necessary; otherwise, the following return a value of FALSE:

    template <class charT, class traits, class Allocator>
    basic_string<charT, traits, Allocator> operator<=(
            const basic_string<charT, traits, Allocator>& lhs,
            const basic_string<charT, traits, Allocator>& rhs);
    template <class charT, class traits, class Allocator>
    basic_string<charT, traits, Allocator> operator<=(const charT* lhs,
            const basic_string<charT, traits, Allocator>& rhs);
    template <class charT, class traits, class Allocator>
    basic_string<charT, traits, Allocator> operator<=(
            const basic_string<charT, traits, Allocator>& lhs,
            const charT* rhs);

The following `operator>=` functions return a value of TRUE if lhs >= rhs, where lhs and rhs are converted into strings if necessary; otherwise, the following return a value of FALSE:

    template <class charT, class traits, class Allocator>
    basic_string<charT, traits, Allocator> operator>=(
            const basic_string<charT, traits, Allocator>& lhs,
            const basic_string<charT, traits, Allocator>& rhs);
    template <class charT, class traits, class Allocator>
    basic_string<charT, traits, Allocator> operator>=(const charT* lhs,
            const basic_string<charT, traits, Allocator>& rhs);
    template <class charT, class traits, class Allocator>
    basic_string<charT, traits, Allocator> operator>=(
            const basic_string<charT, traits, Allocator>& lhs,
            const charT* rhs);

The swap Function

The following swaps the contents (that is, the data members) of lhs and rhs:

    template <class charT, class traits, class Allocator>
    void swap(basic_string<charT, traits, Allocator>& lhs,
      basic_string<charT, traits, Allocator>& rhs);

Inserters and Extractors

The following extracts characters from stream is into str until either end-of-file occurs on is or whitespace is encountered in is; Any leading whitespace is skipped and str is erased before the extraction:

    template <class charT, class STR_traits, class STR_Alloc>
    istream& operator>>(istream& is, basic_string<charT,STR_traits,STR_Alloc>& str)

The following writes str into the output stream os:

    template <class charT, class STR_traits, class STR_Alloc>
    ostream& operator<<(ostream& os, const basic_string<charT,STR_traits,STR_Alloc>
    & str)

The following extracts up until the delim (or end-of-file) into the is; it does not skip leading whitespace and str is erased before the extraction:

    template <class charT, class STR_traits, class STR_Alloc>
    istream& getline(istream& is, basic_string<charT,STR_traits,STR_Alloc>& str,
    charT delim = '\n')

## 7.5.3 The basic_string typedefs

The following typedefs are provided in the basic_string class:

> ### traits

> Is the type used to represent the character traits class used in the string. The traits class provides character primitives such as assignment, comparison, `find()` , `length()` , `copy()` , `move()` , and `assign()` .

> ### value_type

> Is the type of the charT elements in the string, for example `char` or `wchar_t` .

> ### allocator_type

> Is the type of the allocator. The default is `allocator<value_type>` .

> ### size_type

> Is the type used to represent the index into the string. The default is `size_t` .

> ### difference_type

> Is the type used to represent the result of arithmetic operations on the iterators. The default is `ptrdiff_t` .

> ### reference

> ### const_reference

> Is the type used to represent a reference (or const reference) of `value_type` .

> ### pointer

> ### const_pointer

> Is the type used to represent a pointer (or const pointer) to `value_type` .

> ### iterator

> ### const_iterator

> Is the type used to iterate over elements of the string.

> ### reverse_iterator

> ### const_reverse_iterator

> Is the type used to iterate over elements of the string. This typedef differs from iterator in that ++ will move backward through the string and -- will move forward through the string.

## 7.5.4 Upgrading from the Nonstandard Compaq C++ Class Library String Package

The Compaq C++ basic_string Library is designed to replace the nonstandard Compaq C++ String Package.

The following discussion guides you through upgrading nonstandard code to use the new basic_string Library.

- Change `#include <string.h>` or `#include <string.hxx>` to `#include <string>` .
- Change all declarations of `String` to `string` (uppercase S to lowercase s).
- The String Package allowed assignment of a string directly to a `char *` ; however, the basic_string Library does not allow this. You can assign the string's `const char*` representation using the `c_str()` or `data()` basic_string member functions. For example:

      string s("abc");
      char* cp = s; // not allowed
      const char* cp = s.data(); // ok

  The state of the string is undefined if the result of `data()` is cast to a non-const `char*` and then the value of that `char*` is changed.
- The String Package member functions `upper()` and `lower()` are not in the String Library. You can write these functions as nonmember functions, as follows:

      template <class charT, class traits, class Allocator>
      inline
      basic_string<charT, traits, Allocator>
      upper(const basic_string<charT,traits, Allocator>& str) {
              basic_string<charT, traits, Allocator> newstr(str);
              for (size_t index = 0; index < str.length(); index++)
                      if (islower(str[index]))
                              newstr[index] = toupper(str[index]);
              return newstr;
      }

      template <class charT, class traits, class Allocator>
      inline
      basic_string<charT, traits, Allocator>
      lower(const basic_string<charT,traits, Allocator>& str) {
              basic_string<charT, traits, Allocator> newstr(str);
              for (size_t index = 0; index < str.length(); index++)
                      if (isupper(str[index]))
                              newstr[index] = tolower(str[index]);
              return newstr;
      }

  Then instead of calling `upper()` and `lower()` as member functions of the basic_string, pass the string as an argument. For example:

      s2 = s1.upper(); // does not compile
      s2 = upper(s1); // ok

- The String Package `match()` member function does not exist. Equivalent functionality exists in the STL algorithm `mismatch()` , although using it is more complicated. For example:

      string s1("abcdef");
      string s2("abcdgf");
      assert(s1.match(s2)==4); // does not compile
      pair<string::iterator,string::iterator> p(0,0); // ok
      p=mismatch(s1.begin(),s1.end(),s2.begin());
      assert(p.first-s1.begin()==4);
      string s3 = s1;
      p=mismatch(s1.begin(),s1.end(),s3.begin());
      assert(p.first == s1.end()); // everything matched

- The String Package `index()` member function does not exist. The String Library equivalent is `find()` .
- The String Package constructor that takes two positional parameters (a start and end position) and constructs a new string does not exist. It is replaced in the String Library with the member function `substr()` . For example:

      string s("abcde");
      string s2 = s1(1,3); // does not compile
      string s2 = s1.substr(1,3); // ok

- Many previously undetected run-time errors now throw standard exceptions in the String Library.

## 7.5.5 Differences Between the basic_string Library and the Guide string Class

This section describes differences between the Compaq C++ basic_string Library and the string class described in the STL Tutorial and Reference Guide (the Guide string class). The Guide string class was included with the original STL implementation provided by the Hewlett-Packard Company.

The major difference between the basic_string Library and the Guide string class is that the basic_string Library can be treated directly as an STL container. The Guide string class can be used as an STL container only if you explicitly apply the conversion operator to `vector<char>` . For example:

    // string class in the Guide
    #include <bstring.h>
    #include <vector.h>

    main() {
            vector<char> v = string("Hello");
            // call an STL algorithm
            sort(v.begin(),v.end());
            for (vector<char>::iterator iter = v.begin(); iter!= v.end(); iter++)
                   cout << (*iter) ;
            cout << endl;
    }

    // equivalent code using the basic_string Library
    #include <string>

    main() {
            string s("Hello");
            // call an STL algorithm
            sort(s.begin(),s.end());
            for (string::iterator iter = s.begin(); iter!= s.end(); iter++)
                    cout << (*iter) ;
            cout << endl;
    }

A minor difference is that the basic_string Library uses the header file `<string>` not `<bstring.h>` . Also, the header file `<bstring.h>` automatically included `<vector>` whereas `<string>` does not.

The basic_string Library is also fully functional; that is, it supports the functions `size()` , `at()` , and `swap()` , plus those member functions that take STL iterators as arguments.

# 7.6 Numeric Limits Class

The Numeric Limits class represents information about arithmetic types. For each arithmetic type, the class provides a combination of the information that can be found in the following:

- `limits.h`
- `float.h`
- LIA-1 (ISO/IEC 10967-1 Information technology---Language independent arithmetic---Part 1: Integer and floating point arithmetic)
- IEEE Standard for Binary Floating-Point Arithmetic

Not all of the information provided by the class members is meaningful for all types. Any value which is not meaningful for a type is set to 0 or false.

## 7.6.1 The numeric_limits Template Class

A synopsis of the numeric_limits class follows.

        template<class T> class numeric_limits {
        public:
          static const bool is_specialized = false;
          inline static T min() throw();
          inline static T max() throw();
          static const int digits = 0;
          static const int digits10 = 0;
          static const bool is_signed = false;
          static const bool is_integer = false;
          static const bool is_exact = false;
          static const int radix = 0;
          inline static T epsilon() throw();
          inline static T round_error() throw();
          static const int min_exponent = 0;
          static const int min_exponent10 = 0;
          static const int max_exponent = 0;
          static const int max_exponent10 = 0;
          static const bool has_infinity = false;
          static const bool has_quiet_NaN = false;
          static const bool has_signaling_NaN = false;
          static const bool has_denorm = false;
          static const bool has_denorm_loss = false;
          inline static T infinity() throw();
          inline static T quiet_NaN() throw();
          inline static T signaling_NaN() throw();
          inline static T denorm_min() throw();
          static const bool is_iec559 = false;
          static const bool is_bounded = false;
          static const bool is_modulo = false;
          static const bool traps = false;
          static const bool tinyness_before = false;
          static const float_round_style round_style = round_toward_zero;
        };

Specializations are provided for the following types:

        numeric_limits<char>
        numeric_limits<signed char>
        numeric_limits<unsigned char>
        numeric_limits<short>
        numeric_limits<int>
        numeric_limits<long>
        numeric_limits<unsigned short>
        numeric_limits<unsigned int>
        numeric_limits<unsigned long>
        numeric_limits<float>
        numeric_limits<double>
        numeric_limits<long double>

Note that the ANSI C++ September 1996 draft includes specializations for the bool and wchar_t types as follows:

    numeric_limits<bool>
    numeric_limits<wchar_t>

However, due to lack of support for these types in the current Compaq C++ compiler, specializations for them are not provided in the library.

## 7.6.2 Numeric Limits Class Member Functions

> ### static T min() throw();

> This function returns the minimum finite value. Its return value is equivalent to `CHAR_MIN` , `SHRT_MIN` , `FLT_MIN` , `DBL_MIN` , and so forth. For floating types with denormalization, the function returns the minimum positive normalized value. This function is meaningful for specializations where `is_bounded` is not equal to false or `is_bounded` is equal to false and `is_signed` is equal to false.

> ### static T max() throw();

> This function returns the maximum finite value. Its return value is equivalent to `CHAR_MAX` , `SHRT_MAX` , `FLT_MAX` , `DBL_MAX` , and so forth. The function is meaningful for all specializations in which `is_bounded` is not equal to false.

> ### static T epsilon() throw();

> This function returns machine epsilon. Its return value is equivalent to `FLT_EPSILON` , `DBL_EPSILON` , or `LDBL_EPSILON` . The function is meaningful for all floating point types.

> ### static T round_error() throw();

> This function returns the maximum rounding error.

> ### static T infinity() throw();

> This function returns the representation of positive infinity if it is available. The function is meaningful for all specializations for which `has_infinity` is true. It is required by specializations for which `is_iec559` is true.

> ### static T quiet_NaN() throw();

> This function returns the representation of a quiet `Not a Number` if it is available. The function is meaningful for all specializations where `has_quiet_NaN` is not false. It is is required in specializations where `is_iec559` is true.

> ### static T signaling_NaN() throw();

> This function returns the representation of a signaling `Not a Number` if it is available. The function is meaningful for all specializations where `has_signaling_NaN` is not false. It is required in specializations for which `is_iec550` is true.

> ### static T denorm_min() throw();

> This function returns the minimum positive denormalized value. It is meaningful for all floating point types. It is required in specializations for which `has_denorm` is false.

## 7.6.3 Numeric Limits Class Data Members

> ### const bool is_specialized;

> This data member is used to distinguish between types that have specializations and types that do not. If a specialization exists `is_specialized` is true, otherwise it is false.

> ### const int digits;

> This data member indicates the number of radix digits that can be represented. For integer types this is the number of nonsign bits in the representation. For floating point types this is the number of radix digits in the mantissa and is equivalent to `FLT_MANT_DIG` , `DBL_MANT_DIG` , or `LDBL_MANT_DIG` .

> ### const int digits10;

> This data member indicates the number of base 10 digits that can be represented without change. It applies to all specializations where `is_bounded` is true. For floating point types `digits10` is equivalent to `FLT_DIG` , `DBL_DIG` , or `LDBL_DIG` .

> ### const bool is_signed;

> This data member indicates whether a type is signed or not. It applies to all specializations.

> ### const bool is_integer;

> This data member indicates whether a type is an integer or not. It applies to all specializations.

> ### const bool is_exact;

> This data member is true if a type has an exact representation. All integer types are exact. It applies to all specializations.

> ### const int radix;

> For floating types this data member specifies the base or radix of the exponent and is equivalent to `FLT_RADIX` . For integer types it specifies the base of the representation.

> ### const int min_exponent;

> This data member indicates the minimum negative integer such that radix raised to the power of one less than that integer is a normalized floating point number. It applies to all floating types and is equivalent to `FLT_MIN_EXP` , `DBL_MIN_EXP` , or `LDBL_MIN_EXP` .

> ### const int min_exponent10;

> This data member indicates the minimum negative integer such that 10 raised to that power is in the range of normalized floating point numbers. It applies to all floating types and is equivalent to `FLT_MIN_10_EXP` , `DBL_MIN_10_EXP` , or `LDBL_MIN_10_EXP` .

> ### const int max_exponent;

> This data member indicates the maximum positive integer such that radix raised to the power one less than that integer is a representable finite floating point number. It applies to all floating types and is equivalent to `FLT_MAX_EXP` , `DBL_MAX_EXP` , or `LDBL_MAX_EXP` .

> ### const int max_exponent10;

> This data member indicates the maximum positive integer such that 10 raised to that power is in the range of representable finite floating point numbers. It applies to all floating types and is equivalent to `FLT_MAX_10_EXP` , `DBL_MAX_10_EXP` , or `LDBL_MAX_10_EXP` .

> ### const bool has_infinity;

> This data member is true if the type has a representation for positive infinity. It applies to all floating types.

> ### const bool has_quiet_NaN;

> This data member is true if the type has a quiet (that is, nonsignaling) `Not a Number` . It applies to all floating types.

> ### const bool has_signaling_NaN;

> This data member is true if the type supports a signaling `Not a Number` . It applies to all floating types.

> ### const bool has_denorm;

> This data member is true for types that support denormalized values. It applies to all floating types.

> ### const bool has_denorm_loss;

> This data member is true if loss of accuracy is detected as a denormalization loss, rather than as an inexact result.

> ### const bool is_iec559;

> This data member is true if the type adheres to the International Electrotechnical Commission (IEC) 559 standard. It applies to all floating types.

> ### const bool is_bounded;

> This data member is true if the set of values represented by the type is finite. All built-in types are bounded. It applies to all specializations.

> ### const bool is_modulo;

> This data member is true if a type is modulo. A type is modulo if you can add two positive numbers and have a result that wraps around to a number less than the two operands. This data member is usually false for floating types, true for unsigned integers and true for signed integers on most machines. It applies to all specializations.

> ### const bool traps;

> This data member is true if the type supports trapping. It applies to all specializations.

> ### const bool tinyness_before;

> This data member is true if tinyness is detected before rounding. It applies to all floating types.

> ### const float_round_style round_style;

> This data member indicates the rounding style for the type. It applies to all floating types. Specializations for integer types return `round_toward_zero` . See Section 7.6.4 for possible values.

## 7.6.4 Numeric Limits Class Data Types

> ### enum float_round_style

> This data type is used to indicate the rounding mode for floating point arithmetic. It contains the following values:

> Value | Rounding Style
> --- | ---
> round_indeterminate | Indeterminable
> round_toward_zero | Toward zero
> round_to_nearest | To the nearest representable value
> round_toward_infinity | Toward infinity
> round_neg_infinity | Toward negative infinity

# 7.7 The auto_ptr Class

The auto_ptr class provides a simple class for smart pointers; it stores a pointer to an object obtained by way of the `new` operator and deletes that object when the auto_ptr object is destroyed. The auto_ptr class provides semantics of strict ownership. After construction an auto_ptr object owns the object whose pointer it holds. When an instantiation of auto_ptr is copied, ownership of the object is transferred to the destination auto_ptr. The behavior is undefined if more than one instantiation of auto_ptr owns the same object at the same time.

The ANSI C++ September 1996 auto_ptr class makes use of member templates for its copy constructor and assignment operator. Because the current Compaq C++ compiler does not support member templates, auto_ptr does not make use of them for copy construction or assignment operations.

## 7.7.1 The auto_ptr Member Functions

> ### explicit auto_ptr(T* p=0) throw();

> Constructs an object of class auto_ptr<T>. The pointer held by the auto_ptr class is initialized to p. The p variable points to an object of type T or a class derived from T for which delete p is defined and accessible, or p is a null pointer.

> ### auto_ptr(const auto_ptr<T>& a) throw();

> Constructs an object of class auto_ptr<T>. The argument a is copied to `*this` . If a owns the held pointer, ownership is transferred to `*this` .

> ### auto_ptr<T>& operator=(const auto_ptr<T>& rhs) throw();

> The argument rhs is copied to `*this` . If rhs owns the held pointer, ownership is transferred to `*this` . If `*this` already owns a pointer (not equal to the pointer owned by rhs), that held pointer is deleted first.

> ### ~auto_ptr();

> If `*this` owns the held pointer, the pointer is deleted.

> ### T& operator*() const throw();

> Returns a reference to the object to which the underlying held pointer points.

> ### T* operator->() const throw();

> Returns the underlying held pointer.

> ### T* get() const throw();

> Returns the underlying held pointer.

> ### T* release() throw();

> Returns the underlying held pointer after releasing ownership of it.

# 7.8 The Standard Exception Library

The standard exception classes are all classes derived from the exception class and are used in the standard library to report errors detected during program execution. A simple example of using this class follows:

    #include <stdexcept>
    #include <string>

    int main() {
            try {
                    string s("abc");
                    if (s.at(4)=='d') ; // out of range
            }
            catch(const exception& e) {
                    cout << e.what() << endl;
            }
            catch(...) {
                    cout << "unknown exception" << endl;
            }
    }

The output from this example is as follows:

    position beyond end of string

Users may also use the standard exception hierarchy to report errors in their own classes.

## 7.8.1 Types of Standard Exceptions

All standard exceptions are rooted at the base class exception. No standard library errors are of type exception (they are always of a more specific or derived type). This class is simply used as base class when a user wants to catch all standard exceptions, as in the previous example.

The six classes derived from exception are: logic_error, runtime_error, bad_exception, bad_alloc, bad_cast, and bad_typeid.

- The logic_error exceptions are used to report errors detectable before the program executes, such as violations of logical preconditions or class invariants.
- The runtime_error exceptions are used to report errors detectable only when the program executes, such as mathematical overflow or underflow.
- The bad_alloc, bad_exception, bad_cast, and bad_typeid exceptions are currently not implemented in the Compaq C++ compiler.

The logic_error class has four derived classes:

> domain_error (used to report domain errors)
> invalid_argument (used to report invalid arguments)
> length_error (used to report an attempt to produce an object whose length exceeds it maximum allowable size)
> out_of_range (used to report an argument value not in its expected range)

The runtime_error class has three derived classes:

> range_error (used to report errors in internal computations)
> overflow_error (used to report an arithmetic overflow error)
> underflow_error (used to report an arithmetic underflow error)

## 7.8.2 The exception Member Functions

> ### exception() throw();

> Constructs an object of class exception.

> ### exception(const exception&) throw();

> Copies an exception object.

> ### exception& operator=(const exception&) throw();

> Assigns an exception object.

> ### virtual ~exception() throw();

> Destroys the exception object.

> ### virtual const char* what() const throw();

> Returns a null-terminated byte string that contains information about the type of error. The contents of the string are implementation dependent. In the Compaq C++ library the string contains an indication of the problem --- that is, `string index out of range` or `invalid string size parameter` .

## 7.8.3 Derived Exception Classes

All of the standard exception classes are derived from class exception; thus, they inherit all of the exception class member functions. The only difference is in the constructor---all have an overridden constructor that takes a string argument; that is:

    class logic_error: public exception {
    public:
     logic_error(const string& what_arg);
    };

    class domain_error: public logic_error {
    public:
     domain_error(const string& what_arg);
    };

    class invalid_argument: public logic_error {
    public:
     invalid_argument(const string& what_arg);
    };

    class length_error: public logic_error {
    public:
     length_error(const string& what_arg);
    };

    class out_of_range: public logic_error {
    public:
     out_of_range(const string& what_arg);
    };

    class runtime_error: public exception {
    public:
     runtime_error(const string& what_arg);
    };

    class range_error: public runtime_error {
    public:
     range_error(const string& what_arg);
    };

    class overflow_error: public runtime_error {
    public:
     overflow_error(const string& what_arg);
    };

    class underflow_error: public runtime_error {
    public:
     underflow_error(const string& what_arg);
    };

# 7.9 The Complex Math Library

A complex number has a real part and an imaginary part. The standard complex library utilizes templates, so that any underlying type can be used to represent these parts. Template specializations are provided for float, double, and long double.

## 7.9.1 Example of Use

A simple example of use is:

    #include <complex>

    int main() {
     complex<double> c1(1,1), c2(3.14,3.14);
     cout << "c2/c1: " << c2/c1 << endl;
    }

Note that you must explicitly link the sys$share:cma$open_rtl.exe library to access the math routines; that is:

    cxxlink prog,sys$input:/opt
    sys$share:cma$open_rtl.exe/share
    <Ctrl Z>

## 7.9.2 Complex Math Member Functions

> ### complex(const T& re = T(), const T& im = T());

> Constructs an object of type complex with the real part set to re and the imaginary part set to im.

> ### complex(const complex<T>& c);

> Constructs a complex number by copying all elements from c.

> ### complex<T>& operator=(const complex<T>& c);

> Assigns c to `*this` and returns `*this` .

> ### complex<T>& operator=(const T& c);

> Assigns c to the real part of `*this` . Sets the imaginary part of `*this` to zero and returns `*this` .

> ### complex<T>& operator+=(const complex<T>& c);

> Adds c to `*this` and then returns the result.

> ### complex<T>& operator-=(const complex<T>& c);

> Subtracts c from `*this` and then returns the result.

> ### complex<T>& operator*=(const complex<T>& c);

> Multiplies c and `*this` and then returns the result.

> ### complex<T>& operator/=(const complex<T>& c);

> Divides `*this` by c and then returns the result.

> ### T real();

> Returns the real part of `*this` .

> ### T imag();

> Returns the imaginary part of `*this` .

## 7.9.3 Complex Math Nonmember Functions

> ### template <class T>

> ### T real(const complex<T>& c);

> Returns the real part of c.

> ### template <class T>

> ### T imag(const complex<T>& c);

> Returns the imaginary part of c.

> ### template <class T>

> ### T abs(const complex<T>& c);

> Returns the magnitude of c.

> ### template <class T>

> ### T norm(const complex<T>& c);

> Returns the squared magnitude of c.

> ### template <class T>

> ### T arg(const complex<T>& c);

> Returns the phase angle of c.

> ### template <class T>

> ### complex<T> conj(const complex<T>& c);

> Returns the complex conjugate of c.

> ### template <class T>

> ### complex<T> polar(const T& rho, const T& theta = 0);

> Returns the complex value corresponding to a complex number whose magnitude is rho and whose phase angle is theta.

> ### template <class T>

> ### complex<T> cos(const complex<T>& c);

> Returns the complex cosine of c.

> ### template <class T>

> ### complex<T> cosh(const complex<T>& c);

> Returns the complex hyperbolic cosine of c.

> ### template <class T>

> ### complex<T> exp(const complex<T>& c);

> Returns the complex base e exponential of c.

> ### template <class T>

> ### complex<T> log(const complex<T>& c);

> Returns the complex natural (base e) logarithm of x.

> ### template <class T>

> ### complex<T> log10(const complex<T>& c);

> Returns the complex common (base 10) logarithm of x.

> ### template <class T>
> complex<T> pow(const complex<T>& x, int y); template <class T> complex<T> pow(const complex<T>& x, int y); template <class T> complex<T> pow(const complex<T>& x, const complex<T>& y);

> ### template <class T>
> complex<T> pow(const complex<T>& x, const T& y); template <class T> complex<T> pow(const T& x, const complex<T>& y);

> Returns the complex power of base x raised to the y-th power.

> ### template <class T>

> ### complex<T> sin(const complex<T>& c);

> Returns the complex sine of c.

> ### template <class T>

> ### complex<T> sinh(const complex<T>& c);

> Returns the complex hyperbolic sine of c.

> ### template <class T>

> ### complex<T> sqrt(const complex<T>& c);

> Returns the complex square root of c, in the range of the right half-plane.

> ### template <class T>

> ### complex<T> tan(const complex<T>& c);

> Returns the complex tangent of c.

> ### template <class T>

> ### complex<T> tanh(const complex<T>& c);

> Returns the complex hyperbolic tangent of c.

## 7.9.4 Complex Math Nonmember Operators

> ### template <class T>
> complex<T> operator+(const complex<T>& lhs, const T& rhs);

> ### template <class T>
> complex<T> operator+(const T& lhs, const complex<T>& rhs);

> Adds rhs to lhs and returns the sum.

> ### template <class T>
> complex<T> operator+(const complex<T>& lhs, const T& rhs);

> ### template <class T>
> complex<T> operator+(const T& lhs, const complex<T>& rhs);

> Subtracts rhs from lhs and returns the difference.

> ### template <class T>
> complex<T> operator*(const complex<T>& lhs, const T& rhs);

> ### template <class T>
> complex<T> operator*(const T& lhs, const complex<T>& rhs);

> Multiplies rhs and lhs and returns the product.

> ### template <class T>
> complex<T> operator/(const complex<T>& lhs, const T& rhs);

> ### template <class T>
> complex<T> operator/(const T& lhs, const complex<T>& rhs);

> Divides rhs into lhs and returns the quotient.

> ### template <class T>
> complex<T> operator==(const complex<T>& lhs, const T& rhs);

> ### template <class T>
> complex<T> operator==(const T& lhs, const complex<T>& rhs);

> Compares lhs to rhs and returns true if they are equal, otherwise returns false. The imaginary parts of the scalars are assumed to be the value `T()` .

> ### template <class T>
> complex<T> operator!=(const complex<T>& lhs, const T& rhs);

> ### template <class T>
> complex<T> operator!=(const T& lhs, const complex<T>& rhs);

> Compares lhs to rhs and returns true if they are not equal, otherwise returns false. The imaginary parts of the scalars are assumed to be `T()` .

> ### template <class T, class charT, class traits>

> ### istream& operator>>(istream& is, complex<T>& c);

> Extracts a complex number c from the istream is of the form `u` , `(u)` , or `(u,v)` , where `u` is the real part and `v` is the imaginary part. If bad input is encountered, sets `ios::failbit` .

> ### template <class T, class charT, class traits>

> ### ostream operator<<(ostream& os, const complex<T>& c);

> Returns os `<< "(" << c.real() << "," << c.imag() << ")"` .

## 7.9.5 Complex Math Typedefs

> ### typedef T value_type;

> The type used to represent the real and imaginary parts of the complex number.

## 7.9.6 Unsafe Downcasts

Because the Compaq C++ compiler does not yet support the `explicit` keyword (that is, nonconverting constructors), unsafe downcasts will be allowed; that is, users can convert a `complex<double>` to a `complex<float>` .

## 7.9.7 Upgrading from the Nonstandard Complex Math Library

This section explains how to upgrade from the pre-ANSI Compaq C++ complex library to the current Compaq C++ standard complex library, which is based on the 24 September 1996 ANSI C++ working draft.

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

Also note that mathematical error checking is not supported in the ANSI library. Users who rely on detection of underflow, overflow, and divide by zero should continue using the pre-ANSI Compaq C++ complex library. The following is a detailed list of important changes:

- Change `#include <complex.h>` or `#include <complex.hxx>` to `#include <complex>` .
- Change all declarations of complex to complex<double>, for example:

      complex c;

  to:

      complex<double> c;

- The `polar()` function no longer supplies a default value of 0 for the second argument. Users will have to explicitly add it to any calls that have only one argument, for example:

      complex c;
      c = polar(c); // get polar

  to:

      complex<double> c;
      c = polar(c,0.0);

- If you are calling a mathematical function or mathematical operator that takes scalars as arguments ( `polar()` for example), then you must adjust the arguments you pass in to be the same type as the complex template parameter type. For example, you would have to change:

      complex c = polar(0,0);
      complex c2 = c+1;

  to:

      complex<double> c = polar(0.0,0.0); // 0.0 is double
      complex<double> c2= c + 1.0; // 1.0 is double

- The complex_zero variable is not declared in the complex header file. If you want to use it, you will have to declare it yourself. For example, add the following to the top of your source file:

      static const complex<double> complex_zero(0.0,0.0);

- The `sqr()` and `arg1()` functions are no longer provided in Compaq C++. If you want to continue to use them, you should define them in one of your own headers, using the following definitions.

      template <class T>
      inline complex<T> sqr(const complex<T>& a)
      {
         return complex<T>(real(a) * real(a) - imag(a) * imag(a),
              2 * real(a) * imag(a));
      }

      template <class T>
      inline T arg1(const complex<T>& a)

      {
          double val = arg(a);

          if(val > -M_PI && val <= M_PI)
              return val;

          if(val > M_PI)
              return val - (2*M_PI);

          // val <= -PI
          return val + (2*M_PI);
      }

- The `pow(complex, int)` function is no longer provided. You must use `pow(complex<double>, double)` This means changing calls such as:

      pow(c,1);

  to:

      pow(c,1.0);

  This may yield different results if the function previously was underflowing or overflowing, it may not happen anymore.
- The complex output operator (<<) does not insert a space between the comma and the imaginary part. If you want the space you would need to print the real and imaginary parts separately, adding your own comma and space; that is:

      complex<double> c;
      cout << "(" << c.real() << ", " << c.imag() << ")"; // add extra space

- The complex input operator (>>) does not raise an Objection if bad input is detected, it instead sets input stream's state to `ios::failbit` .
- Floating point overflow, underflow, and divide by zero do not set `errno` and will cause undefined behavior. Compaq plans to do complex error checking and error notification in a subsequent release.
- You should no longer need to explicitly link your program with the complex library. It is automatically linked in as part of the standard library. You still have to explicitly link in the C math library, however. (See Section 7.9.1 for how to do this.)

# 7.10 The Allocator Class

The Standard C++ Library defines an allocator class that is used to control the memory model containers will use. Every container class in the Standard C++ library takes an allocator as one of its template arguments. In this way each container can manage its own storage requirements. Containers can make use of different memory models by using allocators that implement different types of memory management schemes. A default allocator that makes use of the global new and delete is provided by the Standard library.

The allocator as defined in the 24 September 1996 draft C++ Standard makes use of member function templates and member class templates. The lack of member template support in the current version of Compaq C++ mandates the use of an allocator that does not utilize this feature. Therefore, the Compaq C++ library provides an alternate allocator class. The alternate allocator allocates raw bytes of storage. Its types and functions are provided by an allocator_interface class. Under this scheme the allocator makes use of the allocator_interface class to allocate typed storage rather than allocating itself directly. The implementation is not standard conforming so its use will be documented in this section.

Note that the current version of the Compaq C++ library also contains a specialization for void. The specialization for void does not conform to standard either. Please refer to the 24 September 1996 ANSI C++ draft for details on the ANSI C++ draft conforming allocator.

The rest of this section defines the allocator provided with the current version of Compaq C++. It also describes how to build custom allocators and containers that make use of this allocator class.

## 7.10.1 Allocator Class Member Functions

> ### allocator();

> Default allocator constructor.

> ### ~allocator();

> Allocator destructor.

> ### void * allocate (size_type n, void * = 0)

> Allocate n*size_type bytes of storage.

> ### void deallocate (void* p)

> Deallocate the storage pointed to by p.

> ### size_type max_size (size_type size) const

> Returns the largest size for which allocate might succeed.

## 7.10.2 The allocator_interface Class

The allocator_interface class excepts two input parameters, an alternate allocator and the type of the objects to be allocated. The class has the following syntax:

    template <class Allocator,class T>
    class allocator_interface {
        //...
    }

## 7.10.3 The allocator_interface Member Functions

> ### allocator_interface();

> Default constructor.

> ### allocator_interface(const Allocator& a);

> Constructs an allocator_interface and stores the allocator object internally.

> ### pointer address (T& x);

> Returns the address of the reference x as a pointer.

> ### size_type max_size () const;

> Returns the largest size for which allocate() of an object of type T might succeed.

> ### pointer allocate(size_type n, pointer = 0)

> Allocates n*sizeof(T) bytes of storage aligned appropriately of objects of type T. Throws bad_alloc if storage can not be obtained. The second parameter is intended to be used to allocate memory at a particular location.

> ### void deallocate(pointer p)

> Deallocates the storage that p points to.

> ### void construct(pointer p, const T& val)

> Constructs an object of type T with an initial value of val at the location specified by p.

> ### void destroy(T* p)

> Calls the destructor on the object that p points to but do not delete the object.

## 7.10.4 Designing Customized Allocators

Allocators can be designed to provide a customized memory management model. To do this, define an allocator that has the same interface as the library allocator.

The following is an example of a customized allocator class that supports the Compaq C++ allocator:

      template <class T>
      class shared_allocator
      {
        public:
          typedef size_t size_type;
          typedef ptrdiff_t difference_type;
          shared_allocator() {;}
          ~shared_allocator() {;}
          void * allocate(size_type n, void* = 0) {
            return (void*) new size_t[n];
          }
          void deallocate (void *p) {
            delete(p);
          }
          size_type max_size (size_type size) const {
            return 1 > UINT_MAX/size ? size_type(1) : size_type(UINT_MAX/size);
          }
      }; // end shared_allocator<T>

      class shared_allocator<void>
      {
        public:
          typedef size_t    size_type;
          typedef ptrdiff_t difference_type;
          typedef void*         pointer;
          typedef const void*   const_pointer;
          typedef void          value_type;
          shared_allocator() {;}
          ~shared_allocator() {;}
          void * allocate (size_type n, void *  = 0) {
            return (void *) new size_t[n];
          }
          void deallocate (void* p) {
            delete(p);
          }
          size_type max_size (size_type size) const {
            return 1 > UINT_MAX/size ? size_type(1) : size_type(UINT_MAX/size);
          }
    }; // shared_allocator<void>

## 7.10.5 Using Custom Allocators with Standard Library Containers

Custom allocators are easily used with existing standard library containers. You need only to provide an allocator type when you instantiate a container as follows:

        vector <int, shared_allocator<int> > v1;
        list <int, shared_allocator<int> > l1;

## 7.10.6 Implementing Custom Containers that Use the Allocator

To implement custom containers, your container must define the following:

- A private typedef to refer to the type of the allocator. The typedef uses the allocator_interface class because the allocator uses the allocator_interface class to get type information.
- A private allocator object data member.

The following is a sample of what a container might look like:

    template <class T, class Allocator>
    class my_container {
    private:
        typedef allocator_interface<Allocator,T> value_alloc_type;
        Allocator  my_allocator;
    }

    Any member function which allocates elements needs to do:

        value_alloc_type(my_allocator).allocate(n,0);

    Any member function which deallocates elements needs to do:

        value_alloc_type(my_allocator).deallocate(p);

Previous | Next | Contents | Index

privacy and legal statement