3

I found this code and I understand what it does (prints if var is type of float) but I can't understand how:

#include <stdio.h>
#include <stdlib.h>

#define typename(x) _Generic((x), float: "float")

#define isCompatible(x, type) _Generic(x, type: true, default: false)

int main(){
  float var; 
  if(isCompatible(var, float))
    printf("var is of type float!\n");
}

What is typename(x)? Why is never called? Also I can't understand this construct:

_Generic(x, type: true, default: false)

And here is there a way to not pass float as parameter and make it implicit?

if(isCompatible(var, float))
  • What do you mean by "make it implicit"? That would seem to defeat the point. – interjay May 20 '18 at 10:20
  • 1
    And you should read this: http://en.cppreference.com/w/c/language/generic – interjay May 20 '18 at 10:20
  • @interjay I mean, if i always want to know if a data is type of float, i think it's not necessary to pass **float** as parameter and define the macro in another way. –  May 20 '18 at 10:24
  • If you want to know if a variable is compatible with type T, obviously you would need to tell the compiler what T is. If you just want a `IsCompatibleWithFloat` macro that only works with `float`, you can just hardcode `float` in there instead of making it a parameter. – interjay May 20 '18 at 10:29
  • @interjay It's exactly what i'd like to do but what do you mean with "hardcore float in there"? –  May 20 '18 at 10:37
  • Remove the `type` parameter and write `float` instead of it. – interjay May 20 '18 at 10:40

2 Answers2

3

I suspect you want to look at the documentation for _Generic here - it's a C11 feature (C11 standard (ISO/IEC 9899:2011) s 6.5.1.1 Generic selection (p: 78-79)). See also the accepted answer here.

In essence in this example, the isCompatible macro calls _Generic and (via type: true) returns true if x (the first argument) is compatible with type type, else false.

The macro typename is not used, but returns the text float if the the argument is compatible with float. For why there is something defined but not used you would have to ask the author of the code.

abligh
  • 24,573
  • 4
  • 47
  • 84
0

Why typename is never called is a question you should ask the developper of the code snippet...

The _Generic keyword is a C11 feature. The idea is to generate different code depending of the type of a variable.

C does not have a typeof operator like Java, thus what in Java looks like

...
if(typeof(p) == typeof(double)) {
    System.out.println("Got type 1");
} 
if(typeof(p) == typeof(char)) {
     System.out.println("Got type 2");
}
...

can be achieved through _Generic in C11 via

#include <stdio.h>

#define PRINT_MY_TYPE_NUMBER(x) _Generic((x), \
    double: printf("Got type 1\n"),\
    char: printf("Got type 2\n") \
)

int main(int c, char** v) {

    double p = 10;

    PRINT_MY_TYPE_NUMBER(p));

}

Note: _Generic does not support arbitrary, but only 'simple' types.

The idea behind isCompatible(variable, type) is to return true if variable has a type compatible to type. It depends on type being passed over, and therefore its depends type being passed, making type implicitly passed over renders the isCompatible useless IMHO.

Michael Beer
  • 853
  • 5
  • 12