|  |  HP C++ HP C++Class Library Reference Manual
 
 
 
 Chapter 3generic 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:
 
  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.
Define the class body as a macro:
 
  
    | 
 
#define YOUR_CLASS_NAMEdeclare(TYPE_PARAMETER_NAME) class {...}; 
#define YOUR_CLASS_NAMEimplement(TYPE_PARAMETER_NAME) ...
 
 | 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.
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.
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
GPTIs 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; 
} 
       |  
 
 
 
 |