Проверка, является ли тип структурой или указателем во время компиляции в C? - PullRequest
0 голосов
/ 31 января 2019

ПРИМЕЧАНИЕ: это НЕ дубликат вопроса, связанного Полом Т., потому что я спрашиваю, возможно ли определить, имеет ли тип определенный более широкий неполный тип / вид во время компиляции,нет, если символ был зарегистрирован во время компиляции.Это похоже на фундаментальное недопонимание вопроса.

Я пишу библиотеку на C, которая имеет дело с псевдообщими функциями, которые принимают тип в качестве аргумента через оболочку макроса.

Чтобы сэкономитьВ деталях (потому что они довольно сложные) есть две возможные функции, которые могут помочь, я думаю:

  • Возможность определить, является ли тип указателем во время компиляции.(Нет, трюк «использовать _Generic для проверки, если вы получите ptrdiff_t из вычитания» не будет работать, потому что структуры возможны, и вы не можете вычесть структуры.)

  • Существовозможность определить, является ли тип структурой во время компиляции.(Если бы это было возможно, то вышеупомянутый трюк _Generic мог бы использоваться, если тип был обнаружен как не являющийся структурой.)

Я перепробовал все, что мог придумать на Годболте (даже пытаясь сравнить типы с неполными анонимными структурами и играть с __builtin_types_compatible_p) и не смог найти никаких решений.

Если у кого-то есть какие-либо решения, я бы с удовольствием их увидел, в противном случае я мог бы просто получитьнемного усложнить дизайн - так что не конец света, если это невозможно, но было бы идеально, если это можно сделать.

Чтобы дать общее представление о том, как может выглядеть один из этих макросовили ожидаемый результат:

int *a;
assert(!IS_STRUCT(a));
assert(IS_POINTER(a));
struct {} b;
assert(IS_STRUCT(b));
assert(!IS_POINTER(b));

не должен выдавать никаких ошибок.

Ответы [ 2 ]

0 голосов
/ 31 января 2019
  1. Это невозможно в стандарте C. Все возможные решения должны определяться реализацией.

  2. Кажется, C не подходит для вашего языка.проблемный домен.Если не считать эзотерических платформ, которые поставляются без поддержки C ++, кажется, что есть мало причин для решения этой проблемы в C. На большинстве платформ, где доступен C, так же как и в C ++.Поскольку вы утверждаете, что используете gcc, то C ++ наверняка доступен, и вы можете обрабатывать некоторые входные данные с помощью компилятора C ++.Вы могли бы выполнить обработку ввода как шаг генератора: запустить код через компилятор C ++, чтобы сгенерировать исходный код, который определяет константы, которые захватывают искомые свойства типа.

0 голосов
/ 31 января 2019

Полный ответ (если используется внешний интерфейс EDG):

Если ваша IDE / компилятор использует внешний интерфейс EDG C ++ (что очень много), и вы используете C ,не C ++ (что предлагает ваш тег), и вы говорите, что используете typeof, тогда вы можете обнаружить структуры следующим образом ( см. последнее руководство, стр. 75 ):

/* Test if EDG Front End is used*/
#if defined(__EDG__) && defined(__EDG_VERSION__)
#define IS_STRUCT(expression_or_type_name) __is_class(typeof (expression_or_type_name)))
#endif

так как в C __ is_class () будет истинно только для struct (http://www.cplusplus.com/reference/type_traits/is_class/).

Далее, указатели могут аналогично обнаруживаться следующим образом:

/* Test if EDG Front End is used*/
#if defined(__EDG__) && defined(__EDG_VERSION__)
#define IS_POINTER(expression_or_type_name) (__is_convertible_to(typeof (expression_or_type_name), void*) || __is_convertible_to(typeof (expression_or_type_name), void const*) || __is_convertible_to(typeof (expression_or_type_name), void volatile*) || __is_convertible_to(typeof (expression_or_type_name), void const volatile*))
#endif

(http://www.cplusplus.com/reference/type_traits/is_convertible/)

...