Generic in C?



  • Hallo zusammen,

    ich habe eine Funktion, die die folgende Signatur hat:

    void foo(float*, float*, float* r);
    

    Nun ist das Problem, dass ich an einer Stelle exakt dieselbe Funktion brauche, jedoch mit dieser Signatur:

    void foo(float*, int*, float* r);
    

    Bis jetzt behelfe ich mir mit der Überladung der Funktion. Doch finde ich das nicht sehr schön, weil der Code bis auf einen Typ derselbe ist. Ich möchte Codeduplicate vermeiden.

    In C++ würde ich jetzt zu einem Template greifen. Gibt es in C auch eine schöne Möglichkeit?

    Vielen Dank
    LG, freakC++



  • Makros. Mit Makros lassen sich Templates ganz gut simulieren.

    Aber idR schreibt man den Code dann 2mal und schaut dass man nicht beide Varianten braucht.



  • Für Makros ist die Methode zu komplex. Naja, dann werde ich es wohl so stehen lassen müssen



  • freakC++ schrieb:

    Für Makros ist die Methode zu komplex. Naja, dann werde ich es wohl so stehen lassen müssen

    Ich würde, wie gesagt nicht unbedingt Markos verwenden wollen. Aber zu komplex - das gibt es da eigentlich nicht.

    Ausschnitt aus einem alten Code von mir:

    #define MAKE_VECTOR(type)									\
    struct CTL_##type##VECTOR {									\
    	size_t	BlockSize;										\
    	type*	value;											\
    	size_t	size;											\
    	size_t	alloc;											\
    };															\
    															\
    typedef struct CTL_##type##VECTOR ctl_##type##Vector;		\
    															\
    ctl_##type##Vector* ctl_##type##VectorInitSize(int BlockSize)\
    {															\
    	ctl_##type##Vector* s=malloc(sizeof(ctl_##type##Vector));\
    	if(!s)													\
    	{														\
    		return NULL;										\
    	}														\
    	s->BlockSize	= BlockSize;							\
    	s->value		= malloc(s->BlockSize*sizeof(type));	\
    	if(!s->value)											\
    	{														\
    		ctl_errno	= CTL_OUT_OF_MEMORY;					\
    		s->size		= 0;									\
    		s->alloc	= 0;									\
    		return NULL;										\
    	}														\
    	s->alloc		= s->BlockSize;							\
    	s->size			= 0;									\
    	return s;												\
    }
    


  • freakC++ schrieb:

    Bis jetzt behelfe ich mir mit der Überladung der Funktion.

    In C gibt es keine Überladung. Bist du sicher, dass du da C programmierst?



  • Für sowas nimmt man (generische) Funktionszeiger, z.B.

    enum  {TypF,TypI};
    void foof(float*, float*, float* r){}
    void fooi(float*, int  *, float* r){}
    
    ...
    struct {void (*fz)();int typ;} dispatcher;
    dispatcher.fz=foof;
    dispatcher.typ=TypF;
    dispatcher.fz(1.0,2.0,3.0);
    ...
    dispatcher.fz=fooi;
    dispatcher.typ=TypI;
    dispatcher.fz(1.0,2,3.0);
    
    bzw. Laufzeitauswertung mittels Typinfo:
    switch( dispatcher.typ ) {
    case TypF: dispatcher.fz(1.0,1.0,1.0);break;
    case TypI: dispatcher.fz(1.0,2,3.0);break;
    }
    


  • Was genau bringt das?

    Also was ist der Vorteil zur herkoemmlichen Methode eines

    void name_f(float, float, float);
    void name_i(float, int, float);
    

    ?



  • Das bringt das was ein generischer Zeiger immer bringt: alle Funktionen mit beliebiger Parameterliste (aber gleichem Rückgabewert) können vom Zeiger aufgenommen werden und wenn man die Funktionen in unterschiedliche Module aufteilt und jeweils dort mit static schützt, können sie sogar gleich heißen.



  • C11:

    _Generic
    


  • Tim schrieb:

    C11:

    _Generic
    

    die auswahl der compiler, die das unterstützen ist aber noch sehr überschaubar



  • Ja, leider ist das noch so.


Anmelden zum Antworten