[an error occurred while processing this directive]

HP OpenVMS Systems

C++ Programming Language
Content starts here HP C++

HP C++
Class Library Reference Manual


Previous Contents Index


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 int s, list of String s, or list of lists of String s.
    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


Previous Next Contents Index