Как мне создать фабричную функцию C? - PullRequest
3 голосов
/ 13 декабря 2010

У меня есть структура, которая принимает указатель на функцию, например:

typedef int (*node_transition_func)( wint_t );

typedef struct lex_dfa_arc_t {

    node_transition_func func;
    int expected_return_val;
    struct lex_dfa_node_t * node;

} LEX_DFA_ARC_T;

И теперь я хочу создать функцию, которая возвращает функцию прототипа "int func (wint_c);"Например:

node_transition_func input_equals( wint_t input, wint_t desired ) { ... }

Возможно ли в C, чтобы вышеуказанная функция действительно работала?Я пытаюсь избежать необходимости определять функцию для каждой буквы (например, input_equals_letter_a, input_equals_letter_b, input_equals_letter_c и т. Д.).

Мой другой подход заключается в том, чтобы просто принять node_transition_func в wint_t и wchar_t *желаемых персонажей, но мне было любопытно, сработает ли мой первый подход.

Спасибо!

Ответы [ 5 ]

4 голосов
/ 13 декабря 2010

Вы можете в основном эмулировать замыкания и каррирование, вместо того, чтобы «возвращать функцию», вы возвращаете структуру, которая имеет указатель на функцию плюс связанные переменные. С парой #defines это может выглядеть даже наполовину в здравом уме.

OTOH, когда вы используете определенный язык, вы должны придерживаться его идиом. Замыкания не являются сильной стороной C. Я предлагаю вам не пытаться быть слишком универсальным в коде C, если вы сомневаетесь, просто используйте switch () {}.

2 голосов
/ 13 декабря 2010

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

1 голос
/ 13 декабря 2010

Похоже, вы пытаетесь делать карри в C (cue clippy :-).Я думаю, что это технически возможно в C. Вы не пытаетесь создавать новые функции.Вы пытаетесь создать альтернативные привязки к существующей функции.В C ++ это довольно просто, но без синтаксического сахара, который стал возможен благодаря метапрограммированию шаблонов (в частности, функторов и привязок), вам пришлось бы делать все это вручную.Ваш другой подход кажется более разумным.

0 голосов
/ 28 октября 2011

Это может быть ближе всего к выполнению карри в C:

    int input_equals_with_type(wint_t Input, wint_t desired) {
        // Do some stuff with regard to different type of "desired"
        return 1;
    }

    #define MAKE_NODE_TRANS_FUNC(type, wint_t desired) \
        int node_transition_func_##type(wint_t input) { \
            return input_equals_with_type(input, desired); \
        }

    MAKE_NODE_TRANS_FUNC(letter_a, letter_a_disired)
    MAKE_NODE_TRANS_FUNC(letter_b, letter_b_desired)
    // and so on...

Ограничение здесь, конечно, в том, что это не "настоящее" карри, так как функции создаются во время компиляции, а невремя выполнения.Но если вы просто пытаетесь создать несколько типов функций, это работает.

0 голосов
/ 13 декабря 2010

Полагаю, эта ваша функция проследит список LEX_DFA_ARC_T и вернет элемент "func" соответствующего элемента?

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...