2012-04-09 3 views
3

Je développe un langage de script en C++ qui utilise des fonctions "intégrées" dans l'interpréteur. J'utilise la construction suivante pour mapper les noms de fonction à leurs pointeurs respectifs:Population automatique de std :: map avec des pointeurs de fonction

typedef void(*BuiltInFunction)(Context*); 
typedef std::unordered_map<std::string, BuiltInFunction> BuiltinFunctionsMap; 

Context est une classe personnalisée.

J'ai des déclarations de fonctions comme celle-ci:

namespace BuiltIns { 
    void _f_print(Context* context); 
    void _f_error(Context* context); 
    void _f_readline(Context* context); 
    void _f_read(Context* context); 
    void _f_readchar(Context* context); 
    void _f_eof(Context* context); 
    ... 
} 

Et enfin une routine qui remplit la carte avec les pointeurs réels:

BuiltinFunctionsMap BuiltIns::populateFunctions() { 
    BuiltinFunctionsMap funcMap; 
    // Standard I/0 
    funcMap["print"] = &BuiltIns::_f_print; 
    funcMap["error"] = &BuiltIns::_f_error; 
    funcMap["readline"] = &BuiltIns::_f_readline; 
    funcMap["read"] = &BuiltIns::_f_read; 
    funcMap["readchar"] = &BuiltIns::_f_readchar; 
    funcMap["eof"] = &BuiltIns::_f_eof; 
    ... 
    return funcMap; 
} 

Ce que je vous demande est de savoir s'il y a un moyen de générer automatiquement la fonction de population à partir de la déclaration de fonction en utilisant des modèles ou quelque chose de similaire. Actuellement, j'utilise une expression régulière, ce qui est assez simple mais je dois le faire chaque fois que j'ajoute de nouvelles fonctions et que c'est lourd.

+3

Je suis assez nouveau pour C++. Je serais très heureux d'envisager une meilleure solution :) – Tibor

+0

'std :: function' est votre ami. Ce peut être un pointeur de fonction ou un objet fonction, ce qui signifie qu'il peut y avoir beaucoup, beaucoup de choses. Les pointeurs de fonction sont incroyablement restrictifs, alors que 'std :: function' permet beaucoup de liberté. – Puppy

+0

Si vous pouvez le faire avec des expressions régulières, ne pouvez-vous pas ajouter cela comme une étape dans votre processus de construction? – alexisdm

Répondre

1

Je ne sais pas si cela est vraiment une réponse utile, mais vous pouvez utiliser le préprocesseur de faire quelques pretty squirrelly stuff:

#include <iostream> 
#include <map> 
#include <string> 

class Context {}; 
typedef void (*BuiltInFunction)(Context*); 

// a list of your function names 
#define FN_NAMES \ 
X(foo) \ 
X(bar) \ 
X(baz) 

// this declares your functions (you also have to define them 
// somewhere else, e.g. below or in another file) 
#define X(a) void _f_ ## a ## _print(Context *context); 
namespace BuiltIns { 
    FN_NAMES 
} 
#undef X 

// a global map initialized (using C++11's initializer syntax) 
// to strings mapped to functions 
#define X(a) {#a, &BuiltIns::_f_ ## a ## _print}, 
std::map<std::string, BuiltInFunction> g_fns = { 
    FN_NAMES 
}; 
#undef X 

int main() { 
    g_fns["foo"](NULL); // calls BuiltIns::_f_foo_print(NULL) 
} 

// (these have to be defined somewhere) 
namespace BuiltIns { 
    void _f_foo_print(Context *context) { 
    std::cout << "foo\n"; 
    } 
    void _f_bar_print(Context *context) { 
    std::cout << "bar\n"; 
    } 
    void _f_baz_print(Context *context) { 
    std::cout << "baz\n"; 
    } 
} 

Cette approche a l'avantage de générer automatiquement par exemple la chaîne "foo" et l'attachant à la fonction _f_foo_print. Les inconvénients sont la supercherie préprocesseur horrible et le fait que vous avez encore à faire face à foo en deux endroits.

1

Vous pouvez détecter automatiquement certains types de fonctions à l'aide donnée T, type, metaprogramming- par exemple de modèle que vous pouvez répondre à la question programatically « Est-ce que T ont un operator+? ». Mais dans le cas général, vous ne pouvez pas faire ce que vous faites ci-dessus automatiquement dans la langue.

Questions connexes