Можно ли определить функцию, используя определение типа обратного вызова? - PullRequest
4 голосов
/ 05 ноября 2019

Я заинтересован в определении функции с использованием предопределенного типа обратного вызова.

Давайте предположим, что я определил тип обратного вызова:

typedef BOOL (*is_trigger_required_cb)(void);

Теперь я хотел бы объявить и определить функциюиспользуя вышеуказанный тип.

Я хотел бы сделать что-то вроде:

is_trigger_required_cb my_func { /* function implementation which accepts void and returns BOOL */ }

Это не скомпилируется из-за:

ошибка: ожидается ';'после объявления верхнего уровня

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

Ответы [ 3 ]

3 голосов
/ 05 ноября 2019

typedef is_trigger_required_cb - это не псевдоним типа функции, а указатель на функцию . Кроме того, C11 6.9.1p2 говорит, что

идентификатор, объявленный в определении функции (который является именем функции), должен иметь тип функции, как указано в части объявления. определения функции. [162]

со сноской 162, в которой говорится, что

162) Намерение состоит в том, что категория типа в определении функции не может быть унаследована от typedef [... ]

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

1 голос
/ 05 ноября 2019

Вы можете приблизиться к нему, если определите функцию типов.

typedef BOOL is_trigger_required_cb(void);

, которые сделают обратный вызов явным указателем (что я считаю плюсом)

is_trigger_required_cb *cb;

и позволит вам по крайней мере объявить функции с этим типом:

is_trigger_required_cb my_func;
BOOL my_func (void) {
  // Do stuff
}

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

Однако это может показаться загадочным, поскольку это обычно не замечают. Я предлагаю вам сравнить его достоинства с необходимостью объяснить это.

0 голосов
/ 05 ноября 2019

Нет, вы не можете этого сделать. Вы можете использовать эти определения типов только для указателей на функции. Вы можете определить только тип функции, как Storyteller в своем ответе. Но, как вы можете видеть, это не делает вещи лучше. Мое решение тоже не подходит.

Используйте макрос (нет, не делайте этого)

Единственное, что вы можете сделать, но я бы настоятельно рекомендовал это сделать, это использовать макрос:

#define f(fname) BOOL fname (void)

f(foo) {
    return 1;
}

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

#define binary_bool(fname, arg1, arg2) BOOL fname (arg1, arg2)

binary_bool(equals,x,y) {
    return x==y;
}

Опять же, я советую против этого. Я просто показываю, что нечто подобное тому, что вы хотите, теоретически возможно. Подобные макросы часто усложняют отладку.

TL; DR

Нет, вы не можете сделать это хорошим способом в C

...