2010-12-13 6 views
2

J'ai un struct qui prend un pointeur de fonction, comme ceci:Comment créer une fonction d'usine C?

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; 

Et maintenant, je veux créer une fonction qui renvoie une fonction du prototype « int func (wint_c); » Par exemple:

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

Est-il possible en C de faire fonctionner la fonction ci-dessus? J'essaie d'éviter de devoir définir une fonction pour chaque lettre (par exemple, input_equals_letter_a, input_equals_letter_b, input_equals_letter_c, etc.). Mon autre approche serait de faire en sorte que node_transition_func prenne un wint_t et un wchar_t * des caractères désirés, mais j'étais curieux de savoir si ma première approche fonctionnerait.

Merci!

+0

Je n'étais pas au courant du terme 'currying' jusqu'à présent, et j'ai trouvé ce fil qui explique beaucoup à ce sujet: http://stackoverflow.com/questions/1023261/is-there-a-way-to -do-currying-in-c – Scott

Répondre

2

Vous ne pouvez pas créer dynamiquement de nouvelles fonctions dans C. Étant donné qu'il s'agit d'un langage compilé et que le compilateur ne fait pas partie de l'environnement d'exécution standard, tout le code doit être défini statiquement au moment de la compilation.

+0

En fait, ce n'est pas 100% vrai. Vous pourriez avoir votre propre mini-compilateur générer du code compilé (peut-être à partir de blocs de construction prédéfinis de code compilé), le coller dans la mémoire quelque part et ensuite l'appeler. En fonction des restrictions du noyau sur l'utilisation de la mémoire bien sûr.Cependant, si vous voulez écrire du code auto-modifiable, peut-être qu'une autre langue comme LISP pourrait être plus appropriée. – AlastairG

0

Je suppose que cette fonction de votre traverserait une liste de LEX_DFA_ARC_T et retournerait le membre "func" d'un élément correspondant?

Il n'y a aucune raison pour que cela ne fonctionne pas. Après tout, un pointeur de fonction tel que node_transition_func n'est encore qu'un pointeur. Cela dit, ce n'est peut-être pas la meilleure solution.

Cependant, je suis un peu confus quant à savoir si ma supposition est correcte à cause des autres choses que vous dites. Peut-être qu'un peu plus de contexte pourrait nous aider à vous répondre.

1

On dirait que vous essayez de faire currying en C (cue clippy :-). Je pense que c'est techniquement possible en C. Vous n'essayez pas de créer de nouvelles fonctions. Vous essayez de créer des liaisons alternatives à une fonction existante. C'est assez simple en C++, mais sans le sucre syntaxique rendu possible par la métaprogrammation de template (en particulier les foncteurs et les bindings), vous devrez faire tout cela manuellement. Votre autre approche semble plus raisonnable.

4

Vous pouvez fondamentalement émuler les fermetures & en cours d'exécution au lieu de "renvoyer une fonction" vous renvoyez une structure qui a le pointeur de fonction plus les variables liées. Avec quelques #defines, il peut même sembler raisonnable. OTOH, quand vous utilisez une langue particulière, vous devriez s'en tenir à ses idiomes. Les fermetures ne sont pas le point fort de C. Je suggère que vous n'essayez pas d'être trop générique dans le code C, en cas de doute, utilisez simplement switch() {}.

0

Cela pourrait être le plus proche, vous pouvez arriver à faire taitement en 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... 

La limitation ici est bien sûr que ce n'est pas « vrai » taitement car les fonctions sont créées au moment de la compilation et ne pas courir temps. Mais si vous essayez juste de faire quelques types de fonctions, alors cela fonctionne.

Questions connexes