ASarkar
ASarkar

Reputation: 529

Overloading a function with void

Trying to overloading a function in C programming language with _Generic. Have found examples:

This the example:

#include <stdio.h>
#include <math.h>

void display_float(float dispid) ;
void display_int(int dispid) ;
void display_void(void) ;

#define display(x) _Generic((x), \
          float: display_float, \
          int: display_int,  \
          default: display_float  \
)(x)

void display_void(void){
    printf("display id: 0\n") ;
}

void display_float(float dispid){
   printf("display id: %f\n", dispid) ;
}

void display_int(int dispid){
    printf("display id: %d\n", dispid) ;
}

void main(void){

    display(5) ;
    display(6.5) ;
}

Now I also want to overload the function with display(). Meaning the function would intake a void, call the function display_void(), and display 0. Can't seem to do this. Any help would be appreciated.

EDIT 1:

Also, see the examples here. One of the examples (I think) is passing a pointer to a void. Can this be implemented?

Upvotes: 1

Views: 2055

Answers (2)

Trying to overloading a function in C programming language

C11 does not have any function overloading and _Generic is for genericity, not for overloading, check that by reading n1570. Consider switching to C++ (or even better, Rust) which provides function overloading. Notice that it is illegal to have a void (not void*, just void) argument to a C function, so there is no any "top" super-type in C, which would be a super type of other types (and this because of calling conventions and ABI considerations making C a low-level programming language, sometimes even called a "portable assembler"). Read more about abstract interpretation and type systems please.

If _Generic was for overloading, the members of the C11 standard committee - all programming language experts and good enough English writers - would have named it like _Overload, but they wisely did not.

Food for thought (assuming both stderr and stdin works like you want them to work) :
what about some hypothetical display(stderr) or display(*stdin) or display("abc") ?

(a wrong suggestion below, followed by a better advice)

bad approach

(this does not work!)

Your display_void should take some argument, e.g.

void display_void(void*p) { printf("p@%p\n", p);

Then you might have:

#define display_anything(P) display_void((void*)(&(P)))

with

#define display(x) _Generic((x), \
      float: display_float, \
      int: display_int,  \
      default: display_anything  \
)(x)

better advice

Since that does not work (and it does not), design your code in some other way. For example, consider having some tagged union, like here. Look into GVariant (from Glib) implementation for inspiration.

Upvotes: 1

KamilCuk
KamilCuk

Reputation: 141493

Sure. Overload Macro on Number of Arguments.

void display_float(float dispid) ;
void display_int(int dispid) ;
void display_void(void) ;

#define _display_1(x) _Generic((x), \
          float: display_float, \
          int: display_int,  \
          default: display_float  \
)(x)
#define _display_0()  display_void()
#define _display_N(_0,_1,N,...)  _display_ ## N
#define display(...) _display_N(_0,##__VA_ARGS__,1,0)(__VA_ARGS__)

int main() {
    display();
    display(1);
    display(1.1);
}

Tested on godbolt.

Note that , ##__VA_ARGS__ is a gcc extension not described in the C standard.

Upvotes: 5

Related Questions