2009-12-05 49 views
4

升壓配備了一個例子文件中Boost的Interpreter.hpp例如類成員函數

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 ...)就是票,我只是不確定實現它的最佳方式。

感謝

+0

該示例的register_function使用invoker :: apply函數創建一個綁定對象,fusion :: nil用於填充序列args參數fusion :: invoke requires。 它不像在該綁定中添加類ptr那麼簡單,我需要將類指針放入構建序列操作中。我假設類指針需要是序列中的第一個元素,但不是100%確定,不是很多文檔http://www.boost.org/doc/libs/1_41_0/libs/fusion/doc/html /fusion/functional/invocation/functions/invoke.html – Charles 2009-12-05 23:24:42

+0

Alexandre Deschamps'reponse應該被標記爲正確的答案 – Catskul 2012-04-17 22:46:20

回答

7

我一直在這個問題上,我已經有點成功,使升壓解釋接受成員函數,例如:

// 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方法將fork「invoke」apply方法,遵循模板。
  • 主要問題是成員callable builtin的第一個參數是保存被調用方法的對象。
  • 據一個我所知,MPL無法解析的不是調用內置的其他東西(即一個boost ::綁定結果)

所以,需要做的是簡單地增加一個步驟是什麼的爭論到「解析」應用,這將是將相關對象添加到應用循環!這裏有雲:

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

在翻譯::調用

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

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生成所需數量的模板

1

我不融入,因此看不到如何解決它在一個簡單和優雅的方式(我主要沒有看到如何成員函數應該工作),但我的something similar工作可能是你的替代品。
如果您想查看結果,請參閱Firebreath資源庫。

簡而言之:

主要的變化可能涉及剝離FB特定的類型,在調用函數之前標記輸入序列並提供您自己的轉換函數。

+0

一些有趣的代碼,看起來像它非常類似於我想要的以及示例代碼在做什麼,除了使用成員函數。 我可以說我們都遇到了同樣的問題,並且您選擇了變種途徑。我也可能會在那裏結束,但我不禁想到它可能會更乾淨。像這個例子一樣的自動sigck tockenizer和轉換器將是理想的。 – Charles 2009-12-06 04:13:44

+0

由於它們來自腳本環境,因此必須採用變體路由,也可以將字符串饋入。但我同意,融合的例子看起來很優雅。我很好奇,儘管他們支持成員職能。 – 2009-12-06 12:07:53

相關問題