Previous: ccnames struct table, Up: ccnames [Contents][Index]
The macros for “well known trait functions” define an API to implement trait struct
types; an trait is a set of operations we can apply to a data struct; multiple data struct
types can implement multiple traits. The following macros are defined in the header file
ccnames.h.
Given an trait type name, an optional struct name and an optional variant specification: expand into the function type name of trait implementation constructors. Constructors of such type must build instances of TRAIT_TYPE as implemented by STRUCT_TYPE, as specified for the variant VARIANT.
Given an trait type name, a struct type name, an optional variant specification: expand into the
name of the API function new() that instantiates that variant of the trait for the
struct.
Given an trait type name and an optional variant specification: expand into the name of the methods table type for the trait type.
Given an trait type name, a struct type name, and an optional variant specification: expand into
the name of the methods table for that variant of the trait implementation for the struct
type.
Given an trait type name, an optional variant specification, and a method name: expand into the type name of the method function for that variant of the trait implementation.
Given an trait type name, a struct type name, an optional variant specification, and a method name: expand into the name of the method function for that variant of the trait implementation for the struct type.
Let’s say we have this struct definition:
typedef struct my_coords_t my_coords_t;
struct my_coords_t {
double X;
double Y;
};
and we want to define an trait type my_printable_T to print the struct on a
standard stream, both in rectangular and polar forms.
Every trait must have a struct acting as table of pointers to functions, whose functions
implements the trait methods. The trait struct type is unique, the methods table
struct type is unique; for every data struct that implements the trait: we need a methods
table and an trait constructor.
The trait struct type and the methods table struct type are defined as follows:
typedef struct my_printable_T my_printable_T;
typedef struct ccname_trait_table_type(my_printable_T) \
ccname_trait_table_type(my_printable_T);
struct my_printable_T {
ccname_trait_table_type(my_printable_T) const * methods;
ccstructs_core_t const * self;
};
typedef void ccname_trait_method_type(my_printable_T, print) \
(my_printable_T I, FILE * stream);
struct ccname_trait_table_type(my_printable_T) {
ccname_trait_method_type(my_printable_T, print) * print_rec;
ccname_trait_method_type(my_printable_T, print) * print_pol;
};
The my_printable_T trait API is defined as follows:
my_printable_T
my_printable_new (ccstructs_core_t const * S,
ccname_trait_table_type(my_printable_T) const * M)
{
my_printable_T I = {
.methods = M,
.self = S
};
return I;
}
ccstructs_core_t const *
my_printable_self (my_printable_T I)
{
return I.self;
}
void
my_printable_print_rec (my_printable_T I, FILE * stream)
{
I.methods->print_rec(I, stream);
}
void
my_printable_print_pol (my_printable_T I, FILE * stream)
{
I.methods->print_pol(I, stream);
}
The implementation of my_printable_T for the data struct my_coords_t is
defined as follows:
static void
ccname_trait_method(my_printable_T, my_coords_t, print_rec) (my_printable_T I, FILE * stream)
{
CCSTRUCTS_PC(my_coords_t, S, my_printable_self(I));
fprintf(stream, "X=%f, Y=%f\n", S->X, S->Y);
}
static void
ccname_trait_method(my_printable_T, my_coords_t, print_pol) (my_printable_T I, FILE * stream)
{
CCSTRUCTS_PC(my_coords_t, S, my_printable_self(I));
double RHO = hypot(S->X, S->Y);
double THETA = atan2(S->Y, S->X);
fprintf(stream, "RHO=%f, THETA=%f\n", RHO, THETA);
}
static ccname_trait_table_type(my_printable_T) const ccname_trait_table(my_printable_T, my_coords_t) = {
.print_rec = ccname_trait_method(my_printable_T, my_coords_t, print_rec),
.print_pol = ccname_trait_method(my_printable_T, my_coords_t, print_pol)
};
my_printable_T
ccname_trait_new(my_printable_T, my_coords_t) (my_coords_t * S)
{
return my_printable_new(ccstructs_core(S), &ccname_trait_table(my_printable_T, my_coords_t));
}
We can use the trait as follows:
int
main (void)
{
cce_location_t L[1];
my_coords_t * S;
my_printable_T I;
if (cce_location(L)) {
cce_run_catch_handlers_final(L);
} else {
S = ccname_new(my_coords_t, rec)(L, 1.0, 2.0);
I = ccname_trait_new(my_printable_T, my_coords_t)(S);
my_printable_print_rec(I, stdout);
my_printable_print_pol(I, stdout);
ccname_delete(my_coords_t)(S);
}
exit(EXIT_SUCCESS);
}
Previous: ccnames struct table, Up: ccnames [Contents][Index]
This document describes version 0.3.0-devel.3 of CCStructs.