DEC C++
Class Library Reference Manual


Previous Contents Index

#include <complex.h>


DECLARATION


class c_exception 
{ 
    friend complex   exp(const complex &); 
    friend complex   sinh(const complex &); 
    friend complex   cosh(const complex &); 
    friend complex   log(const complex &); 
    friend int       complex_error(c_exception &); 
 
public: 
    int              type; 
    char             *name; 
    complex          arg1; 
    complex          arg2; 
    complex          retval; 
 
public: 
    c_exception(char *, const complex &, const complex & = complex_zero); 
}; 


DESCRIPTION

Objects of this class handle exceptions for complex arithmetic. This includes information on functions, parameters, error types, and default return values.


DATA MEMBERS

complex arg1

Is the left argument of the function that incurred the error.

complex arg2

Is the right argument of the function that incurred the error.

char *name

Is the name of the function that incurred the error.

complex retval

Is the value to be returned by the function that incurred the error. You may use the complex_error(c_exception &) function to change this value.

int type

Is one of these kinds of error: SING, OVERFLOW, or UNDERFLOW.

CONSTRUCTOR

c_exception(char *function_name, const complex &function_arg1, const complex &function_arg2 = complex_zero)

Constructs a complex arithmetical exception object, with reference to the name and arguments of the function that incurred the error.

OTHER FUNCTION

int complex_error (c_exception &error_information)

Is the default error-handling function that is called by certain complex arithmetical functions in this package (namely, cosh, exp, log, and sinh) when those functions detect an arithmetical error. You may replace this function with your own function that takes an identical parameter list and returns a value as specified in the following table:
Return Value from Error-handling Function Action Taken by Complex Arithmetical Function
0 Set the global value errno ; if the error type is SING , print an error message.
non 0 Do not set errno ; do not print an error message.

To substitute your own error-handling function, pass a pointer to your function to the set_complex_error function. (See the Function section under Global Declarations for the complex package.)

The complex arithmetical functions that invoke the error handling function always return the value specified in error_information.retval. Your error-handling function may set this value.


Chapter 3
generic Package

The generic package provides ways to simulate parameterized types by allowing the instantiation of class declarations using the macro facilities of the C++ preprocessor. You can use the generic package to construct container classes. The actual types of the data members are passed at compile time as parameters to the class when you use the class name.

To declare a generic type:

  1. Define a name for the class and specify the number of type parameters:


    #define YOUR_CLASS_NAME(TYPE_PARAMETER_NAME) name2(TYPE_PARAMETER_NAME, YOUR_CLASS_NAME) 
    

    To specify two type parameters, use the name3 macro.

  2. Define the class body as a macro:


    #define YOUR_CLASS_NAMEdeclare(TYPE_PARAMETER_NAME) class {...}; 
    #define YOUR_CLASS_NAMEimplement(TYPE_PARAMETER_NAME) ...
     
    

  3. Declare the actual class:


    declare(YOUR_CLASS_NAME, ACTUAL_TYPE_NAME) 
    

    By substituting one or another class of ACTUAL_TYPE_NAME, you can declare multiple instances of the generic class template with various component types. For example, depending on the type parameter you use, you can declare such types as list of ints, list of Strings, or list of lists of Strings.
    If it is not a type name, ACTUAL_TYPE_NAME must be a typedef name.
    You must do this in each compilation unit that uses the parameterized type with a given parameter.

  4. Define the functions or static data of the actual class.


    implement(YOUR_CLASS_NAME, ACTUAL_TYPE_NAME) 
    

    You must do this once in each program that uses the parameterized type with a given parameter.

  5. Declare an instance of the class you have declared by specifying objects of type YOUR_CLASS_NAME(ACTUAL_TYPE_NAME), as follows:


    YOUR_CLASS_NAME(ACTUAL_TYPE_NAME) object1, object2; 
    


Global Declarations

These declarations are used by the generic package but they are not members of any class.

HEADER

#include <generic.hxx>

Alternative Header

#include <generic.h>


COMPILE-TIME PARAMETERS

TYPE, TYPE1, TYPE2---The types for which this class is parameterized; TYPE, TYPE1, or TYPE2 must be an identifier.
CLASS---The class that is parameterized. For a vector of integers, for example, CLASS is vector and TYPE is int.

DECLARATIONS


typedef int  (*GPT)(int, char *); 
int          genericerror(int n, char *msg); 


TYPE

GPT

Is a pointer to a generic error-handling function.

FUNCTION

int genericerror (int n, char *msg)

Is the default error-handling function; it prints an error number (n) and message (msg) on cerr and calls abort().

MACROS

Macros provide preprocessor facilities for simulating parameterized types. The following macros are defined for the generic package:

callerror(CLASS, TYPE, N, S)

Calls the current error handler for a given instance of a parameterized class. CLASS denotes the name of the generic class (for example, vector). TYPE denotes the type parameter for which to instantiate the generic class (for example, int to get a vector of integers); the type must be an identifier (for example, char* is not valid). N denotes the first argument to pass to the error handler; the default is the function genericerror(int, char*). S denotes the second argument to pass to the error handler.

declare(CLASS, TYPE)

Declares the class specified by a macro with the name of the generic class. The word declare follows the class name (for example, vectordeclare). It also defines the inline member functions of the class. CLASS denotes the name of the generic class (for example, vector). TYPE denotes the type parameter for which to instantiate the generic class (for example, int to get a vector of integers). The type must be an identifier (for example, char* is not valid).

declare2(CLASS, TYPE1,TYPE2)

Declares the class specified by a macro with the name of the generic class. The name is followed by the word declare2. The declare2 macro differs from the declare macro only in that you use it to declare two type parameters, TYPE1 and TYPE2.

errorhandler(CLASS, TYPE)

Is the name of the pointer to the error handler for a given instance of a parameterized class (for example, intvectorhandler to handle errors for a vector of integers). CLASS denotes the name of the generic class (for example, vector). TYPE denotes the type parameter for which to instantiate the generic class (for example, int to get a vector of integers). The type must be an identifier (for example, char* is not valid).

implement(CLASS, TYPE)

Defines the noninline member functions of a class, specified by a macro with the name of the generic class. The name is followed by the word implement (for example, vectorimplement). The implement macro takes the same arguments as the declare macro.

implement2(CLASS, TYPE1,TYPE2)

Defines the noninline member functions of a class, specified by a macro with the name of the generic class. The name is followed by the word implement2. The implement2 macro differs from the implement macro only in that you use it to declare two type parameters, TYPE1 and TYPE2.

name2(S1,S2)

Concatenates two identifier segments to form a new identifier using the ## operator.

name3(S1,S2,S3)

Concatenates three identifier segments to form a new identifier using the ## operator.

name4(S1,S2,S3,S4)

Concatenates four identifier segments to form a new identifier using the ## operator.

set_handler(CLASS, TYPE, HANDLER)

Specifies a function as the current error handler for a given instance of a parameterized class. Initially, the error-handling function is set to genericerror(int, char*). CLASS denotes the name of the generic class (for example, vector). TYPE denotes the type parameter for which to instantiate the generic class (for example, int to get a vector of integers); the type must be an identifier (for example, char* is not valid). HANDLER denotes a pointer to the function you want to set to the new error handler. Also, you can use the set_handler macro in a function declaration or definition.

Example

The following program shows the use of the genericerror function and associated macros:

extern "C" 
{ 
#include <stdlib.h> 
#include <stddef.h> 
#include <stdio.h> 
} 
 
#include <generic.hxx> 
 
#define my_vector(T) name2(T, my_vector) 
 
// Declare a vector of objects of type T (the class and extern data) 
#define my_vectordeclare(T) \
    class my_vector(T) \
    { \
    private: \
        int s; \
        T *p; \
    public: \
        my_vector(T)(int); \
        ~my_vector(T)(); \
        T &operator[](int); \
    }; \
    extern GPT errorhandler(my_vector, T); \
    extern GPT set_handler(my_vector, T, GPT); 
 
// Implement a vector of objects of type T 
// (Define the functions and global data) 
#define my_vectorimplement(T) \
    my_vector(T)::my_vector(T)(int size) \
    { \
        s = size; \
        p = new T[size]; \
    } \
    my_vector(T)::~my_vector(T)() \
    { \
        delete[] p; \
    } \
    T &my_vector(T)::operator[](int i) \
    { \
        if(i < 0 || i >= s) \
        { \
            callerror(my_vector, T, i, "Index out of bounds"); \
            static T error_object; \
            return error_object; \
        } \
        return p[i]; \
    } \
    GPT errorhandler(my_vector, T) = &genericerror; \
    GPT set_handler(my_vector, T, GPT new_genericerror) \
    { \
        GPT old_genericerror = errorhandler(my_vector, T); \
        errorhandler(my_vector, T) = new_genericerror; \
        return old_genericerror; \
    } 
 
// Declare and implement vector of int 
declare(my_vector, int) 
implement(my_vector, int) 
 
// Error-handling function 
my_handler( 
    int n, 
    char *msg 
    ) 
 
{ 
    fflush(stderr); 
    printf("in my_handler(%d,\"%s\")\n", n, msg); 
    fflush(stdout); 
    return 0; 
} 
 
 
int main(int argc, char *argv[]) 
{ 
    my_vector(int) v1(10); 
 
    GPT old_error_handler; 
 
    // Set the handler to a function that does not abort 
    old_error_handler = set_handler(my_vector, int, &my_handler); 
    v1[12345] = 0; 
 
    // Restore the handler and cause an error 
    // This should abort 
    old_error_handler = set_handler(my_vector, int, old_error_handler); 
    v1[12345] = 0; 
 
    return EXIT_SUCCESS; 
} 


SEE ALSO

vector Package


Chapter 4
iostream Package

Classes in the iostream package provide methods to handle input and output streams, including reading and writing built-in data types. You also can extend certain methods described here to handle class types.

This package includes, among others, the classes ios and streambuf, and the subclasses derived from these base classes. Figure 4-1 shows the inheritance structure of the iostream package. In the diagram, arrows point from the base classes to derived classes.

The istream (input stream) class supports input operations (extractions); the ostream (output stream) class supports output operations (insertions). The iostream class derives from both istream and ostream, and supports both extractions and insertions.

The following stream objects are predefined:
cin An istream_withassign object linked to standard input
cout An ostream_withassign object linked to standard output
cerr An ostream_withassign object linked to standard error that supports unbuffered output
clog An ostream_withassign object linked to standard error that supports buffered output

To generate output, you apply the insertion operator (<<) to cout, as shown in the following example:


cout << "Hello\n" ; 

Figure 4-1 Inheritance Diagram for the iostream Package


Obtaining input is similar to generating output, except that you apply the extraction operator (>>) to cin, as shown in the following example:


int eye, jay ; 
cin >> eye >> jay ; 

If you include these fragments of code in a program, your system expects users to type in two integer values (for eye and jay) from a terminal. The iostream package supplies predefined extraction and insertion operators for all built-in data types, including char*.

This package also supports file manipulation. To connect a specific file to your program, instantiate one of the following class types:

To format within character arrays, the iostream package includes the following associated class types:

Note

On systems with IEEE floating-point arithmetic, certain values may be printed as symbols for Infinity (for example, INF) or Not a Number (for example, NaN).

Deriving Your Own Class from ios

If you derive your own class from the ios class, or from one of its derived classes, the ios subobject must be initialized properly during instantiation. Specifically, you must ensure that the streambuf pointer within the ios subobject is valid.

To do this, you can specify the ios(streambuf*) constructor as a member initializer for your class constructor. Optionally, you can call the ios::init(streambuf*) member function.

Thread Safety

The predefined stream objects, cerr , cin , clog , and cout are thread safe only for individual calls into the DEC C++ Class Library. You must provide synchronization around sequences of calls. For more information on synchronizing access to predefined stream objects, see the section on Global Declarations in this chapter.

User-defined stream objects are not thread safe, so you must provide synchronization around individual calls as well as sequences of calls. For more information on synchronizing access to user-defined objects, see Chapter 6 and the section on Global Declarations in this chapter.

The ios member function sync_with_stdio() is not thread safe. If your application calls this function, it must make the call before any threads use cerr , cin , clog , or cout .


Global Declarations

These declarations are used by the iostream package but they are not members of any class.

HEADER

#include <iostream.hxx>

Alternative Header

#include <iostream.h>


DECLARATIONS


typedef long    streamoff 
typedef long    streampos 
 
ios             &dec(ios &s); 
ios             &hex(ios &s); 
ios             &oct(ios &s); 
ios             &lock(ios &s); 
ios             &unlock(ios &s); 
 
istream         &ws(istream &i); 
ostream         &endl(ostream &o); 
ostream         &ends(ostream &o); 
ostream         &flush(ostream &o); 


TYPES

typedef long streamoff

Is the type representing a character offset into a stream. For more information, see the description of the seekoff and seekpos functions in the streambuf class.

typedef long streampos

Is the type representing a character position in a stream. For more information, see the description of the seekoff and seekpos functions in the streambuf class.

MANIPULATORS

The following functions insert values into a stream, extract values from a stream, or specify the conversion base format. For more information on the conversion base format flags, see the ios class.

ios &dec(ios &s)

Sets the conversion base format for s to decimal, essentially clearing the ios::oct and ios::hex flags and setting the ios::dec flag.

ios &hex(ios &s)

Sets the conversion base format for s to hexadecimal, essentially clearing the ios::oct and ios::dec flags and setting the ios::hex flag.

ios &oct(ios &s)

Sets the conversion base format for s to octal, essentially clearing the ios::dec and ios::hex flags and setting the ios::oct flag.

istream &ws(istream &i)

Extracts (skips) white-space characters from i.

ostream &endl(ostream &o)

Ends a line by inserting a new-line character into o and flushing o.

ostream &ends(ostream &o)

Ends a string by inserting a null '/0' character into o.

ostream &flush(ostream &o)

Flushes o.

SYNCHRONIZING ACCESS TO PREDEFINED STREAM OBJECTS

The following unparameterized manipulators are for use in synchronizing access to the predefined stream objects, cerr, cin, clog, and cout:

ios &lock(ios &s)

Locks s if s is one of the predefined stream objects.

ios &unlock(ios &s)

Unlocks s if s is one of the predefined stream objects.

If your application needs to lock two or more of these objects at the same time, your application must adhere to the following locking order:

  1. cin
  2. cerr
  3. clog
  4. cout

For example, if your application needs to lock both cerr and cout , lock cerr first and cout second. The unlocking order is not important.

Keep in mind that when your application calls a member function for a predefined stream object, the member function will typically lock the object for the duration of the call. Therefore, if your application has locked one of the stream objects and then uses another, this use must also adhere to the predefined locking order. For example, your application should not send output to cerr while cout is locked.

The locking order necessarily matches the default ties between the stream objects as follows:

Any input/output operation on a stream object causes the iostream package to flush the object to which it is tied. Thus, an output to cerr flushes cout .


Examples

#1

#include <iostream.hxx> 
#include <iomanip.hxx> 
 
int main () 
{ 
   int value = 10; 
 
   cout << hex << value << ',';   // Change the base conversion format to 
                                  // hexadecimal; note that the default is 
                                  // decimal as set by the ios constructors. 
 
   cout << value << ',';          // The base conversion format set in the 
                                  // previous line is still active.      
 
   cout << dec << value << endl;  // Change the base conversion format to 
                                  // decimal; lastly, insert a new-line 
                                  // character into the stream and flush 
                                  // cout. 
   return 0; 
} 


Previous Next Contents Index