Automatic collection of std :: map with function pointers
I am developing a script language in C ++ that uses functions that are "built" into the interpreter. I use the following construct to map function names to their corresponding pointers:
typedef void(*BuiltInFunction)(Context*);
typedef std::unordered_map<std::string, BuiltInFunction> BuiltinFunctionsMap;
where Context
is the custom class.
Then I have function declarations:
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);
...
}
And finally, a procedure that populates the map with actual pointers:
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;
}
I am asking if there is a way to automatically generate a population function from a function declaration using templates or something similar. I currently use regex, which is simple enough, but I have to do it every time I add new features, and it's cumbersome.
I don't know if this is really a useful answer, but you can use a preprocessor to do some pretty protein 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 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";
}
}
This approach has the advantage of automatically generating, for example, a string "foo"
and binding it to a function _f_foo_print
. The downsides are horrible preprocessing trickery and the fact that you still have to deal with foo
in two places.
You can automatically detect some kinds of functions through template metaprogramming, for example given the type of T, you can programmatically answer the question "Does T have operator+
?" But in general, you cannot do what you are doing above automatically in the language.