Я понимаю, для чего нужно использовать 'Generic' в C11, и я хотел бы использовать его в статическом утверждении, чтобы гарантировать, что два пользовательских типа (typedefs) - это один и тот же первичный тип.
Я создал макрос, который отображает каждый тип примитива на перечисляемое значение, и проверил, что он работает как нужно.Однако, когда я пытаюсь сравнить равенство двух результирующих макросов из двух типов в статическом утверждении, я получаю ошибку компилятора.Когда вы закомментируете статическое утверждение, код работает как положено.
Похоже, что статическое утверждение оценивается компилятором ПЕРЕД оценкой общего расширения.Может ли это быть так?И куда я могу обратиться, чтобы проверить поведение этого?
Пример кода :
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
typedef enum
{
UTIL_TYPE_ENUM_BOOL,
UTIL_TYPE_ENUM_CHAR,
UTIL_TYPE_ENUM_SCHAR,
UTIL_TYPE_ENUM_UCHAR,
UTIL_TYPE_ENUM_SHORT,
UTIL_TYPE_ENUM_USHORT,
UTIL_TYPE_ENUM_INT,
UTIL_TYPE_ENUM_UINT,
UTIL_TYPE_ENUM_LONG,
UTIL_TYPE_ENUM_ULONG,
UTIL_TYPE_ENUM_LONG_LONG,
UTIL_TYPE_ENUM_ULONG_LONG,
UTIL_TYPE_ENUM_FLOAT,
UTIL_TYPE_ENUM_DOUBLE,
UTIL_TYPE_ENUM_LONG_DOUBLE,
UTIL_TYPE_ENUM_OTHER,
} UtilTypeEnum_t;
// returns the enumerated value representing a primitive type
#define UTIL_TYPE_GET_TYPE_ENUM(x) _Generic((x), \
_Bool: UTIL_TYPE_ENUM_BOOL, \
char: UTIL_TYPE_ENUM_CHAR, \
signed char: UTIL_TYPE_ENUM_SCHAR, \
unsigned char: UTIL_TYPE_ENUM_UCHAR, \
short int: UTIL_TYPE_ENUM_SHORT, \
unsigned short int: UTIL_TYPE_ENUM_USHORT, \
int: UTIL_TYPE_ENUM_INT, \
unsigned int: UTIL_TYPE_ENUM_UINT, \
long int: UTIL_TYPE_ENUM_LONG, \
unsigned long int: UTIL_TYPE_ENUM_ULONG, \
long long int: UTIL_TYPE_ENUM_LONG_LONG, \
unsigned long long int: UTIL_TYPE_ENUM_ULONG_LONG, \
float: UTIL_TYPE_ENUM_FLOAT, \
double: UTIL_TYPE_ENUM_DOUBLE, \
long double: UTIL_TYPE_ENUM_LONG_DOUBLE, \
default: UTIL_TYPE_ENUM_OTHER)
typedef int32_t foo_t;
typedef float bar_t;
// IF YOU COMMENT OUT THE STATIC ASSERT, THE CODE WILL COMPILE AND WORKS AS EXPECTED
_Static_assert((UTIL_TYPE_GET_TYPE_ENUM(foo_t)==UTIL_TYPE_GET_TYPE_ENUM(bar_t)),"ERROR");
int main(void)
{
foo_t foo;
bar_t bar;
printf("foo's type = %d\n", UTIL_TYPE_GET_TYPE_ENUM(foo));
printf("bar's type = %d\n", UTIL_TYPE_GET_TYPE_ENUM(bar));
if (UTIL_TYPE_GET_TYPE_ENUM(foo) != UTIL_TYPE_GET_TYPE_ENUM(bar))
{
printf("Not the same type!\n");
}
else
{
printf("Same type!\n");
}
return 0;
}
#endif
Ошибка компилятора:
$ gcc foo.c
foo.c:35:49: error: expected expression before ‘,’ token
#define UTIL_TYPE_GET_TYPE_ENUM(x) _Generic((x), \
^
foo.c:77:17: note: in expansion of macro ‘UTIL_TYPE_GET_TYPE_ENUM’
_Static_assert((UTIL_TYPE_GET_TYPE_ENUM(foo_t)==UTIL_TYPE_GET_TYPE_ENUM(bar_t)),"ERROR");
^~~~~~~~~~~~~~~~~~~~~~~
foo.c:35:49: error: expected expression before ‘,’ token
#define UTIL_TYPE_GET_TYPE_ENUM(x) (_Generic((x), \
^
foo.c:77:49: note: in expansion of macro ‘UTIL_TYPE_GET_TYPE_ENUM’
_Static_assert((UTIL_TYPE_GET_TYPE_ENUM(foo_t)==UTIL_TYPE_GET_TYPE_ENUM(bar_t)),"ERROR");
^~~~~~~~~~~~~~~~~~~~~~~
foo.c:77:16: error: expression in static assertion is not an integer
_Static_assert((UTIL_TYPE_GET_TYPE_ENUM(foo_t)==UTIL_TYPE_GET_TYPE_ENUM(bar_t)),"ERROR");