United States |
Previous | Contents | Index |
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 YOUR_CLASS_NAME(TYPE_PARAMETER_NAME) name2(TYPE_PARAMETER_NAME, YOUR_CLASS_NAME) |
#define YOUR_CLASS_NAMEdeclare(TYPE_PARAMETER_NAME) class {...}; #define YOUR_CLASS_NAMEimplement(TYPE_PARAMETER_NAME) ... |
declare(YOUR_CLASS_NAME, ACTUAL_TYPE_NAME) |
implement(YOUR_CLASS_NAME, ACTUAL_TYPE_NAME) |
YOUR_CLASS_NAME(ACTUAL_TYPE_NAME) object1, object2; |
These declarations are used by the generic package but they are not members of any class.
#include <generic.hxx>#include <generic.h>
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 .
typedef int (*GPT)(int, char *); int genericerror(int n, char *msg);
GPT
Is a pointer to a generic error-handling 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 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.
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; } |
vector Package
Previous | Next | Contents | Index |