Templates from C++ in C -
trying recreate classes c++ standard library in c. example, std::pair class.
emulate templates, used macros of course. here example of how looks like:
#define _template_pair_struct(t1, t2, tname, strname) \ typedef struct { \ t1* first; \ t2* second; \ } strname; #define _template_pair_new(t1, t2, tname, strname) \ strname* tname##_new() \ { \ strname *new = malloc(sizeof( strname )); \ new->first = malloc(sizeof(t1)); \ new->second = malloc(sizeof(t2)); \ return new; \ }
if trying use structure in multiple source files, have generate code multiple times. that, obviously, leads error.
is there way fix this, can use these "templates" in c?
as others have said, there few things keep in mind, make sure there 1 function definition.
i don't particularly solution here is.
one header rule them (pair.h)
#ifndef template_pair #define template_pair #include <stdlib.h> #define pair_name( t1, t2 ) t1##t2##name #define pair_ptr_name( t1, t2 ) t1##t2##ptr_name #define pair_create( t1, t2) make##t1##t2 #define pair_ptr_create( t1, t2) make_ptr##t1##t2 #define pair_ptr_free(t1, t2) free##t1##t2 #define pair_definition( t1, t2) \ typedef struct { \ t1 first; \ t2 second ; \ } pair_name(t1, t2) #define pair_ptr_definition( t1, t2) \ typedef struct { \ t1* first; \ t2* second ; \ } pair_ptr_name(t1, t2) #define make_pair_declare(t1, t2) pair_name(t1, t2) pair_create(t1, t2) ( const t1& v1, const t2& v2 ) #define make_pair_ptr_declare(t1, t2) pair_ptr_name(t1, t2) pair_ptr_create(t1, t2) ( const t1& v1, const t2& v2 ) #define pair_ptr_free_declare(t1, t2) void pair_ptr_free(t1, t2) ( pair_ptr_name(t1, t2) & pair ) #define make_pair_signature(t1, t2) pair_name(t1, t2) pair_create(t1, t2) ( const t1& v1, const t2& v2 ) #define make_pair_ptr_signature(t1, t2) pair_ptr_name(t1, t2) pair_ptr_create(t1, t2) ( const t1& v1, const t2& v2 ) #define free_pair_ptr_signature(t1, t2) void pair_ptr_free(t1, t2) ( pair_ptr_name(t1, t2) & pair ) #define make_pair_define( t1, t2 ) \ make_pair_signature(t1, t2) { \ pair_name(t1, t2) pair; \ pair.first = v1; \ pair.second = v2; \ return pair; \ } #define make_pair_ptr_define( t1, t2 ) \ make_pair_ptr_signature(t1, t2) { \ pair_ptr_name(t1, t2) pair; \ pair.first = malloc( sizeof(t1) ); \ if ( pair.first != 0 ) *(pair.first) = v1; \ pair.second = malloc( sizeof( t2) ) ; \ if ( pair.second != 0 ) *(pair.second) = v2; \ return pair; \ } #define pair_ptr_free_define( t1, t2 ) \ free_pair_ptr_signature(t1, t2) { \ free( pair.first ); \ free( pair.second ); \ } #endif
one header bring them (defs.h):
#ifndef defs_header #define defs_header #include "pair.h" typedef int* pint; pair_definition( int, int ); pair_definition( int, double ); pair_definition( double, double ); pair_definition( pint, pint ); pair_definition( float, int ); pair_ptr_definition( int, int ); make_pair_declare( int, int ); make_pair_declare( int, double ); make_pair_declare( double, double ); make_pair_declare( pint, pint ); make_pair_declare( float, int ); make_pair_ptr_declare( int, int ); pair_ptr_free_declare( int, int ); #endif
and in darkness bind them (impl.c):
#include "defs.h" make_pair_define( int, int ); make_pair_define( int, double ); make_pair_define( double, double ); make_pair_define( pint, pint ); // manual "instantiation" make_pair_signature( float, int ) { pair_name( float, int ) local; local.first = v1; local.second = v2; return local; } make_pair_ptr_define( int, int ); pair_ptr_free_define( int, int );
in land of main shadows lie:
#include "defs.h" int main(void) { pair_name(int, int) mypairints; pair_name( double, double) mypairdoubles; pair_name( pint, pint) mypairpointers; pair_name( float, int) mypairother; pair_ptr_name( int, int ) pairptr; mypairints = pair_create( int, int ) (1, 2); mypairdoubles = pair_create( double, double ) (5, 6.5); mypairpointers = pair_create( pint, pint) ( 0, 0 ); mypairother = pair_create( float, int) (1, 1); pairptr = pair_ptr_create(int, int) (1, 2 ); pair_ptr_free(int, int) (pairptr ); return 0; }
pair_name
creates structure containing values, pair_ptr_name
contains pointers values. pair_create
, pair_ptr_create
create values , fill data inside pair.
you need define necessary combinations in "impl.c". compilation unit can #include "defs.h"
, use pairs.
edit - answers questions:
- "wouldn't cause trouble when use once in library or of kind , again in program uses both library , pair "template"?"
"pair.h" contains macros, can safely used in library or program.
what's important don't define same function twice. wouldn't define same structure twice either.
you can following though: - take pair.h, defs.h , impl.c above , build them library (add necessary __declspec(dllexport)
, __declspec(dllimport
) - can #include pair.h
, defs.h
, use pairs defined there in program - if want use new pairs, (float, float)
need add new defs_my_program.h
, new impl_my_program.c
declare , define these new pair. defs_my_program.h
header can included along defs.h
header library provides.
you still 1 declaration , 1 definition each pair. "downside" can't (safely) use pairs on-the-fly, need centralized.
- "the way chose type , function names bring issues it. split pair 2 values , 1 2 pointers. need specialisation pair 1 pointer , 1 value, , pair 1 value , 1 pointer. have 4 cases of pairs already. using triplets or higher tuples, have implement 2^n cases."
well, starters, asked std::pair
, not touple.
note std::pair
equivalent of pair_name
, there no std::pair
allocates dynamic memory.
you don't need new specializations if don't need automatically use malloc
. example pint
shows can create s pair
of (int, int*)
or (int*, int)
. it's value of pointer needs come outside pair
.
if want pair
of (int, int*)
automatically allocates memory int*
have add if need it. hope not.
for tuples of values, not optimal solution use pair
of pair
, element. give structure containing 3 elements. can done via macro magics, cutting down on exponential growth worried about.
Comments
Post a Comment