Boost的使用类成员函数的Interpreter.hpp示例

时间:2009-12-05 06:15:25

标签: c++ boost

Boost带有

中的示例文件
  

boost_1_41_0\libs\function_types\example

名为interpreter.hppinterpreter_example.hpp

我正在尝试创建一种情况,其中我有一堆不同参数的函数,返回类型等所有寄存器并被记录到一个位置。然后有能力拉出一个函数并用一些参数执行它。

在这里阅读了几个问题之后,从其他几个问题来看,我认为在这个示例文件中实现的设计与我能够获得的一样好。它需要任何类型的函数,并允许您使用字符串参数列表调用它,该列表被解析为正确的数据类型。 基本上它是一个控制台命令解释器,这可能是它的意思。

我一直在研究代码,并试图获得相同的实现来接受类成员函数,但到目前为止都没有成功。 我想知道是否有人可以建议所需的修改,或者可能在类似的东西上工作并且有相同的代码。

在示例中,您将看到

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

我想做点什么

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

但这打破了任意数量的论点特征。 所以我在想某种自动生成boost :: bind(& test :: classFunc,& x,_1,_2,_3 ......)就是票,我只是不确定实现它的最佳方法

由于

3 个答案:

答案 0 :(得分:7)

我一直在研究这个问题,并且我已经成功地使boost解释器接受了成员函数,例如:

// Registers a function with the interpreter, 
// will not compile if it's 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's 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);

enable_if语句用于防止在编译时使用错误的方法。现在,您需要了解的内容:

  • 它使用boost :: mpl来解析可调用内置函数的参数类型(基本上是函数指针)
  • 然后,在编译时准备一个融合向量(这是一个可以同时存储不同类型不同对象的向量)。
  • 当mpl完成解析每个参数时,“解析”apply方法将在模板后面的“invoke”apply方法中进行分叉。
  • 主要问题是成员可调用内置函数的第一个参数是保存被调用方法的对象。
  • 据我所知,mpl不能解析除可调用内置函数之外的其他参数(即A Boost :: Bind结果)

所以,需要做的只是在“解析”应用中添加一步,即将相关对象添加到apply循环中!在这里:

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());
}
解释器中的

:: 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) );      
}

这样,它只会跳过第一个参数类型并正确解析所有内容。 可以通过以下方式调用该方法:invoker.register_function("SomeMethod",&TheClass::TheMethod,&my_object);

答案 1 :(得分:1)

我没有进入融合,因此没有看到如何以简单而优雅的方式解决它(我主要看不到成员函数应该如何工作),但我在something similar上工作过可能是你的另一种选择 如果您想查看结果,请将其放在Firebreath存储库中。

简而言之:

主要更改可能涉及剥离特定于FB的类型,在调用仿函数之前对输入序列进行标记,并提供自己的转换函数。

答案 2 :(得分:0)

一个选项是制作一组模板

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)) { /*...*/ )

依此类推。在C ++ 0x附带其可变参数模板之前,您可以使用Boost.Preprocessor生成所需数量的模板