1

I'm trying to achieve method overloading in C, preferably using macros so the header/library can handle the definitions and declarations instead of putting that onto the user. Now I've read this answer about using _Generic however the problem is my functions have struct types. So there's no way to evaluate their type using a __typeof__ of _Generic. I wonder if there is any way at all.

This is how my header file looks like (which is all we should be concerned with)-

#pragma once

// Macros for generic like use of the data structure

// Macros for the stack type itself
/*
 * Define stack with corresponding type
 * Converts Stack(int) to intstack_t
*/
#define Stack(type) type stack_t

// Macros for functions
/*
 * Define createStack function
 * Converts createStack(int, 5) to create_intstack(5)
*/
#define createStack(type, capacity) create_ ##type ##stack(capacity)

/*
 * Define destroyStack function
 * Converts destroyStack(someIntStack) to destroy_intstack(someIntStack)
 * Where someIntStack is a pointer to a variable of type intstack_t
*/
#define destroyStack(stack) _Generic(stack, intstack_t*: destroy_intstack, charstack_t*: destroy_charstack)(stack)

/*
 * Define push function
 * Converts push(someIntStack, data) to intstack_push(someIntStack, data)
 * Where someIntStack is a pointer to a variable of type intstack_t
*/
#define push(stack, data) _Generic(stack, intstack_t*: intstack_push, charstack_t*: charstack_push)(stack, data)

// Stack structure definition(s)

// int stack definition
typedef struct IntegerStack {
    int top;
    unsigned capacity;
    int* arr;
}intstack_t;

// char stack definition
typedef struct CharacterStack {
    int top;
    unsigned capacity;
    char* arr;
}charstack_t;

//Stack functions

// int stack functions
intstack_t* create_intstack(int);
void destroy_intstack(intstack_t*);
void intstack_push(intstack_t*, int);

// char stack functions
charstack_t* create_charstack(int);
void destroy_charstack(charstack_t*);
void charstack_push(charstack_t*, char);

Majority of the function declarations (and indirectly, their respective macros) have been removed, as they all essentially function the same. I'm only concerned about the push function macro as provided. The other macros are really there to show what kind of usecase I intend. Obviously the macro used in push using _Generic will not work as intstack_t or charstack_t are not primitive types.

The goal is for the user to be able to use push(stack, data) where the stack can be a variable of either type intstack_t* or charstack_t* and the statement push(stack, data) will be transformed into intstack_push(stack, data) or charstack_push(stack, data) respectively.

10
  • It may be possible, but it'll probably make your code hard to read and maintain. Commented Apr 14, 2020 at 14:32
  • Instead of using a type, use void * and store a pointer to an opaque type. Commented Apr 14, 2020 at 14:41
  • I really don't want to use void pointers as it might make the code type unsafe and open up serious vulnerabilities. I'm fine with the code being difficult to read/maintain but I do not want it to be unsafe unless explicitly needed Commented Apr 14, 2020 at 14:43
  • You've left out the control expression in the _Generic invocation. I assume you meant it to be(stack). But why does it matter that the types are not primitive? Commented Apr 14, 2020 at 19:49
  • @rici my bad, I did not notice I had the param missing. But it won't work for "intstack_t" or "charstack_t" types because _Generic does not allow those, it only allows primitive types like int, long etc Commented Apr 15, 2020 at 5:54

1 Answer 1

2

_Generic will work with any complete type other than a Variable Length Array. And although you cannot associate incomplete types with values in an _Generic invocation, there is no problem with pointers to incomplete types.

So your push macro will work just fine, even if used in a context where instack_t and charstack_t are opaque.

Sample on coliru: http://coliru.stacked-crooked.com/a/7d9b181af2429c5e

Sign up to request clarification or add additional context in comments.

1 Comment

strange, it seems only visual studio clang tools throws errors, when I use clang directly from the commandline it seems to work. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.