The following m4 macro code demonstrates typesafe genering programming in C. Unlike the C qsort() procedure, the following code is type safe. Unlike C++ templates/STL, the generated code yields nice error messages.
I have seen this approach being used by a major, large-scale CAD program with thousands of modules and developers. This project uses the C preprocessor to generate generic C++ data structures such as container classes. The program is very successful in many industries such as automotive and aerospace.
define(swap_generic,
{
$1 temp;
temp = *$2;
*$2 = *$3;
*$3 = temp;
}
)
define(swap_generic_ptr,
{
$1* temp;
temp = $2[$3];
$2[$3] = $2[$4];
$2[$4] = temp;
}
)
define(quicksort_typesafe,
extern int less_than_$1($1,$1);
void quicksort_$1($1 *begin, $1 *end)
{
$1 *ptr;
$1 *split;
if (end - begin < 1)
{
return;
}
ptr = begin;
split = begin + 1;
while (++ptr <= end)
{
if (less_than_$1(*ptr,*begin))
{
swap_generic($1,ptr, split)
++split;
}
}
$1* spm1 = split -1;
swap_generic($1,begin, spm1)
quicksort_$1(begin, spm1);
quicksort_$1(split, end);
})
define(quicksort_typesafe_ptr,
extern int less_than_ptr_$1($1**,int,int);
void quicksort_ptr_$1($1** array, int begin, int end)
{
int ptr;
int split;
if (end - begin < 1)
{
return;
}
ptr = begin;
split = begin + 1;
while (++ptr <= end)
{
if (less_than_ptr_$1(array,ptr,begin))
{
swap_generic_ptr($1,array,ptr, split)
++split;
}
}
int spm1 = split -1;
swap_generic_ptr($1,array,begin, spm1)
quicksort_ptr_$1(array,begin, spm1);
quicksort_ptr_$1(array,split, end);
})
quicksort_typesafe(int);
quicksort_typesafe_ptr(strCust);
#include#include #include struct Customer { char* name; char* street; char* city; int postcode; }; typedef struct Customer strCust; int less_than_ptr_strCust(strCust** array,int posA,int posB) { return strcmp(array[posA]->name, array[posB]->name) < 0; } #include "qs_int.c" void quicksort_int(int*, int*); int less_than_int(int a, int b) { return a < b; } int main(int argc, char** argv) { const int n=20; int toBeSorted[20] = {999,4,55,2,1,1,8888,8,6,4,3,2,1,8888,5,5,5,5,5,5}; quicksort_int(toBeSorted,toBeSorted+n-1); for(int i=0; i < n; i++) { printf("%i ",toBeSorted[i]); } printf("\n"); strCust* customerList[6]; customerList[0] = malloc(sizeof(strCust)); customerList[0]->name = strdup("Boeing Co"); customerList[0]->street = strdup("Grant Avenue"); customerList[0]->city = strdup("Everett"); customerList[0]->postcode = 11111; customerList[1] = malloc(sizeof(strCust)); customerList[1]->name = strdup("Airbus SE"); customerList[1]->street = strdup("Rue de General Foche"); customerList[1]->city = strdup("Toulouse"); customerList[1]->postcode = 11112; customerList[2] = malloc(sizeof(strCust)); customerList[2]->name = strdup("Mercedes Benz"); customerList[2]->street = strdup("Daimlerstr"); customerList[2]->city = strdup("Stuttgart"); customerList[2]->postcode = 21111; customerList[3] = malloc(sizeof(strCust)); customerList[3]->name = strdup("Dassault Aviation"); customerList[3]->street = strdup("Avenue Charles de Gaulle"); customerList[3]->city = strdup("Paris"); customerList[3]->postcode = 14111; customerList[4] = malloc(sizeof(strCust)); customerList[4]->name = strdup("BAE Systems"); customerList[4]->street = strdup("Nelson Square"); customerList[4]->city = strdup("London"); customerList[4]->postcode = 71111; customerList[5] = malloc(sizeof(strCust)); customerList[5]->name = strdup("Saab"); customerList[5]->street = strdup("Akerbogatan"); customerList[5]->city = strdup("Linkoeping"); customerList[5]->postcode = 17111; quicksort_ptr_strCust(customerList,0,5); for(int i=0; i < 6; i++) { printf("%s\n",customerList[i]->name); } }