Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to assert two types are equal in c?

Tags:

c

types

assert

How do I assert that two types are equal in C? In C++, I would use std::is_same, but searching StackOverflow and elsewhere seems only to give results for C++ and C#. Is there no way to do this in C?


Note, this is not asking whether a variable has a certain type but rather whether two types are the same.

like image 523
Zach Boyd Avatar asked Dec 18 '18 20:12

Zach Boyd


2 Answers

How to assert two types are equal in c?

Use _Generic to get you at least mostly there with non-array types.

#define compare_types(T1, T2) _Generic((  (T1){0}  ), \
  T2: "Same", \
  default: "Different" \
)

#include <stdio.h>
#include <stdint.h>

int main() {
  // Same range
  printf("%ld %lld\n", LONG_MAX, LLONG_MAX);
  // Same size
  printf("%zu %zu\n", sizeof (long), sizeof (long long));
  // Yet different
  printf("%s\n", compare_types(long, long long));

  // int64_t is a long on my machine
  printf("%s\n", compare_types(long, int64_t));
  printf("%s\n", compare_types(long long, int64_t));
}

Output

9223372036854775807 9223372036854775807
8 8
Different
Same
Different

Improved

Further, a stronger compare employs a A vs B and B vs A test. The 2 tests are useful for the controlling expression of _Generic converts arrays to pointers of the first element losing some type information.

#define strong_helper(T1, T2) _Generic(( (T1){0} ), \
  T2: 1, \
  default: 0 \
)
#define compare_types_strong(T1, T2) (strong_helper(T1,T2) && strong_helper(T2,T1))

printf("%d\n", compare_types_strong(long, int64_t));
printf("%d\n", compare_types_strong(int [3], int *));

Output

1
0

Still troublesome for arrays and void

compare_types_strong(int [3], int [3]) returns 0 as _Generic converted the controlling expression int [3] to a pointer to the first element type (int *).

@PSkocik, in a deleted comment, points out this approach will not work for the incomplete object type void.

like image 100
chux - Reinstate Monica Avatar answered Nov 15 '22 05:11

chux - Reinstate Monica


Under gcc, you could do something like this:

#define same_type(a, b) \ 
    static_assert(__builtin_types_compatible_p(typeof(a), typeof(b)), "types do not match")

...

int a, b;
float c;
same_type(a,b);
same_type(a,c);
like image 3
dbush Avatar answered Nov 15 '22 05:11

dbush