Boost Interpreter.hpp example with class functions

Boost comes with an example file in

boost_1_41_0\libs\function_types\example

called interpreter.hpp and interpreter_example.hpp

I am trying to create a situation where I have a bunch of functions from different arguments, return types, etc. all are recorded and recorded in one place. Then you have the opportunity to pull out the function and execute it with some parameters.

After reading a few questions here and from several other sources, I think that the design implemented in this example file is as good as I can get. It performs a function of any type and allows you to call it using a list of string arguments, which is analyzed for the desired data types. This is mainly a console interpreter of commands, and probably this is what he wanted to show.

I study the code and dig it out, trying to get the same implementation in order to accept the member functions of the class, but have not yet succeeded. I was wondering if anyone could suggest the necessary changes or maybe work on something similar and have the same code.

In this example you will see

 interpreter.register_function("echo", & echo); interpreter.register_function("add", & add); interpreter.register_function("repeat", & repeat); 

I want to do something like

 test x; interpreter.register_function("classFunc", boost::bind( &test::classFunc, &x ) ); 

But this violates any number of arguments. Therefore, I think that some kind of boost :: bind auto-generator (& test :: classFunc, & x, _1, _2, _3 ...) would be a ticket, I just donโ€™t know how to best implement it.

thanks

+4
source share
3 answers

I am working on this problem, and I have managed to get the boost interpreter to accept a member function, for example:

 // Registers a function with the interpreter, // will not compile if it a member function. template<typename Function> typename boost::enable_if< ft::is_nonmember_callable_builtin<Function> >::type register_function(std::string const& name, Function f); // Registers a member function with the interpreter. // Will not compile if it a non-member function. template<typename Function, typename TheClass> typename boost::enable_if< ft::is_member_function_pointer<Function> >::type register_function(std::string const& name, Function f, TheClass* theclass); 

The enable_if statement is used to prevent the use of the wrong method at compile time. Now what you need to understand:

  • It uses boost :: mpl to analyze, by parameters, the argument of the called inline argument (which is basically a function pointer).
  • Then it prepares a merge vector at compile time (which is a vector that can simultaneously store different objects of different types).
  • When mpl parses all arguments, the parsing method will use the fork in the invoke apply method, following the patterns.
  • The main problem is that the first argument of the member called by the inline is an object that contains the called method.
  • As far as I know, mpl cannot parse the arguments of something other than the called inline (i.e. the result of A Boost :: Bind)

So, what needs to be done, just add one step to the โ€œparsingโ€, which would be to add the corresponding object to the application loop! Here it is:

 template<typename Function, typename ClassT> typename boost::enable_if< ft::is_member_function_pointer<Function> >::type interpreter::register_function( std::string const& name, Function f, ClassT* theclass); { typedef invoker<Function> invoker; // instantiate and store the invoker by name map_invokers[name] = boost::bind(&invoker::template apply_object<fusion::nil,ClassT> ,f,theclass,_1,fusion::nil()); } 

in the interpreter :: invoker

 template<typename Args, typename TheClass> static inline void apply_object( Function func, TheClass* theclass, parameters_parser & parser, Args const & args) { typedef typename mpl::next<From>::type next_iter_type; typedef interpreter::invoker<Function, next_iter_type, To> invoker; invoker::apply( func, parser, fusion::push_back(args, theclass) ); } 

Thus, he will simply skip the first type of argument and analyze everything correctly. The method can be called as follows: invoker.register_function("SomeMethod",&TheClass::TheMethod,&my_object);

+7
source

I'm not in a merger and therefore can not see how to fix it in a simple and elegant way (I mostly do not see how the member functions should work), but I was working on something like this , which can be an alternative for you.
If you want to take a look at the result, it is in the Firebreath repository.

In short:

The main changes are likely to be to break down FB-specific types in order to activate input sequences, invoke input functions, and provide their own conversion functions.

+1
source

One option is to create a set of templates.

 template <class T, class Ret> void register_function(const char *name, Ret (T::*fn)()) { /* boost::bind or your way to register here */ } template <class T, class Ret, class Arg1> void register_function(const char *name, Ret (T::*fn)(Arg1)) { /*...*/ ) 

And so on. Until C ++ 0x comes with its variable templates, you can use Boost.Preprocessor to generate the required number of templates

0
source

All Articles