C++ Boost';带类成员函数的s解释器.hpp示例

C++ Boost';带类成员函数的s解释器.hpp示例,c++,boost,C++,Boost,Boost附带了一个示例文件 boost\u 1\u 41\u 0\libs\function\u types\example 呼叫和 我试图创建一种情况,在这种情况下,我有一组不同参数、返回类型等的函数,所有这些函数都注册并记录到一个位置。然后能够拉出一个函数并使用一些参数执行它 在阅读了这里的一些问题以及其他一些来源之后,我认为在这个示例文件中实现的设计与我能够得到的一样好。它接受任何类型的函数,并允许您使用字符串参数列表调用它,该列表被解析为正确的数据类型。 基本上它是一个控制台命令解释器

Boost附带了一个示例文件

boost\u 1\u 41\u 0\libs\function\u types\example

呼叫和

我试图创建一种情况,在这种情况下,我有一组不同参数、返回类型等的函数,所有这些函数都注册并记录到一个位置。然后能够拉出一个函数并使用一些参数执行它

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

我一直在研究代码,尝试让相同的实现接受类成员函数,但到目前为止都没有成功。 我想知道是否有人可以建议所需的修改,或者可能在类似的工作中使用相同的代码

在示例中,您将看到

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…)将是解决方案,我只是不确定实现它的最佳方式


谢谢

一个选项是制作一组模板

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)) { /*...*/ )
模板
void register_函数(const char*name,Ret(T::*fn)(){/*boost::bind或您在此处注册的方式*/}
模板
void register_函数(const char*name,Ret(T::*fn)(Arg1)){/*…*/)

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

我不喜欢fusion,因此不知道如何以简单而优雅的方式修复它(我主要不知道成员函数应该如何工作),但我研究的可能是您的替代方法。
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)) { /*...*/ )
如果您想查看结果,它就在存储库中

简言之:

  • 包含主要功能
  • 丑八怪会生成那个标题
  • 包含转换为目标类型等实用程序功能
  • 并包含一个单元测试,以显示它的实际作用

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

我一直在解决这个问题,我已经成功地使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);
//向解释器注册函数,
//如果是成员函数,则不会编译。
模板
typename boost::enable_if:type
寄存器函数(std::string const&name,函数f);
//向解释器注册成员函数。
//如果它是非成员函数,则不会编译。
模板
typename boost::如果:type,则启用
register_函数(std::string const&name、函数f、类*TheClass);
enable_if语句用于防止在编译时使用错误的方法。现在,您需要了解的是:

  • 它使用boost::mpl通过可调用内置(基本上是函数指针)的参数类型解析
  • 然后,在编译时准备一个融合向量(该向量可以同时存储不同类型的不同对象)
  • 当mpl解析完每个参数后,“parsing”apply方法将在模板后面插入“invoke”apply方法
  • 主要问题是成员可调用内置函数的第一个参数是保存被调用方法的对象。
  • 据我所知,mpl无法解析除可调用内置(即Boost::Bind result)之外的其他内容的参数
因此,需要做的只是向“解析”应用程序添加一个步骤,即将相关对象添加到应用程序循环中!如下所示:

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());
}
模板
typename boost::如果:type,则启用
解释器::寄存器函数(std::字符串常量和名称,
功能f,
类别*类别);
{   
typedef调用器;
//按名称实例化并存储调用程序
映射调用程序[名称]
=boost::bind(&invoker::template apply_对象)
,f,类,_1,fusion::nil();
}
在解释器中::调用器

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) );      
}
模板
内联函数
无效的
应用对象(函数func,
班级,班级,
参数\u解析器和解析器,
Args常量和Args)
{
typedef typename mpl::next::type next\u iter\u type;
typedef解释器::调用者调用者;
调用程序::apply(func,解析器,fusion::push_back(args,theclass));
}
这样,它将跳过第一个参数类型并正确解析所有内容。
方法可以这样调用:
invoker.register\u函数(“SomeMethod”、&TheClass::TheMethod、&my\u对象)

示例的register_函数使用invoker::apply函数和fusion::nil创建一个bind对象,该对象用于填充序列args参数fusion::invoke requires。这不像在该绑定中添加类ptr那么简单,我需要将类指针放入构建序列操作中。我假设类指针为n需要是序列中的第一个元素,但不是100%确定,没有很多Alexandre Deschamps博士的回复应该被标记为正确的答案一些有趣的代码,似乎它与我想要的和示例代码所做的非常相似,除了成员函数。我可以告诉你,我们都遇到了相同的问题,你可以我想走另一条路我可能也会去那里,