1

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?

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
ASarkar
  • 469
  • 5
  • 16
  • 1
    You can't overload on the absence of a parameter. Your choice of `display_float` as the default in the `_Generic` is surprising, but changing it to `display_void` won't help much; you'd have to provide an argument to the `display` macro, and that would be passed to whatever function is in the `default` clause, and if that was `display_void`, it would be expecting no arguments. However, `_Generic` expects an _assignment-expression_ as the first argument, and neither an empty token sequence nor `()` is acceptable as an _assignment-expression_ so you can't use `_Generic` to overload on `()`. – Jonathan Leffler May 28 '19 at 03:50
  • @JonathanLeffler: I suspected this. But also see my EDIT 1 in the question. – ASarkar May 28 '19 at 04:00
  • 1
    Passing pointer to void is easy — yes, that can be handled. It's passing nothing that is tricky (undoable, I think, even with C11 allowing empty arguments to macros). – Jonathan Leffler May 28 '19 at 04:01
  • 1
    I rolled back your edit. Please do not incorporate answers in your question. It invalidates them, and is quite rude to the people who donate their time to answer. If you have a new question about other updated code, post as new question. – StoryTeller - Unslander Monica May 28 '19 at 05:08
  • Without better examples (or some genuine [MCVE] in your question itself), the question is unclear and I voted to close it. – Basile Starynkevitch May 28 '19 at 06:07
  • `void main(void)` should be `int main(void)`. – Keith Thompson May 28 '19 at 06:23
  • 1
    You could define a `display0` macro that takes no arguments and a `display1` macro that takes one argument. You know when you're writing the call how many arguments you're passing, so choosing which macro to invoke isn't much of a burden. – Keith Thompson May 28 '19 at 06:24
  • @BasileStarynkevitch: A reproducible example is given in the question itself. Not sure what more you are asking for. Everyone else seems to understand perfectly what the question is. – ASarkar May 28 '19 at 07:13
  • As I answered **it is not about function overloading** so at least the title of the question is wrong, and at least that should be improved; and `_Generic` should not even suggests overloading, but genericity – Basile Starynkevitch May 28 '19 at 07:14
  • The original title was edited by someone else. Also, the link that I have provided at the very beginning shows that function overloading in C can be done via `_Generic`. – ASarkar May 28 '19 at 07:21
  • My claim is that it is about generic functions, not function overloading. See the food for thought in my answer. But I am not a native English speaker (and in France I was educated, even at high school, to choose words carefully) – Basile Starynkevitch May 28 '19 at 07:24

2 Answers2

5

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.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • Won't work well with `display(stderr);` or `FILE* f = fopen(__FILE__, "r"); display(f);` or on Linux using [stat(2)](http://man7.org/linux/man-pages/man2/stat.2.html) with `struct stat st; stat("/dev/zero", &st);` followed by `display(st);` or `display(&st)`; please improve your answer for `display(stderr)` – Basile Starynkevitch May 28 '19 at 05:55
  • @BasileStarynkevitch I don't get your point. There is no `display(FILE*)` nor `display(struct stat*)` nor `display(struct stat)` overloads, so they shouldn't work. I don't get your point. If you add them, [they will work](https://godbolt.org/z/zInnn8). Why should `display(stderr)` work? OP didn't requested it. I won't. – KamilCuk May 28 '19 at 05:59
  • OP dreams of a *generic* `display` thing, and I am trying to explain (sorry, I am not a native English speaker) that such a thing cannot exist (unless OP defines `display_FILE` *explicitly* and `display_stat`, which he does not want to!) – Basile Starynkevitch May 28 '19 at 06:01
  • @BasileStarynkevitch ? `Now I also want to overload the function with display(). Meaning the function would intake a void, call the function display_void()` - this is very specific. We want to write `display()` and make it call `display_void()`. Nothing more, nothing less. I don't know OP that good to guess what she/he dreams about and does or doesn't want to. The OPs post has like 6 edits, maybe your browser could have messed it up. – KamilCuk May 28 '19 at 06:08
  • @ Kamil Cuk: then do what I did: vote to close the question as unclear. – Basile Starynkevitch May 28 '19 at 06:37
1

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.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547