3

我想將luabind合併到我的一個項目中。爲此,我需要提供一個與call_function類似的功能(見下文)。這個函數使用了一些模板魔法(禮貌的提升),我會感謝一些幫助。這是我第一次真正遇到模板元編程(就是它被稱爲?),所以我有點迷路。這裏有幾個我會感謝幫助的片段。對於可變長度參數的BOOST_PP_ITERATION

#define LUABIND_TUPLE_PARAMS(z, n, data) const A##n * 
#define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n 

我真的不知道這是什麼預處理位達到,我甚至不知道它叫什麼,以便搜索是有點困難。 A是一個模板類型。如果我沒記錯的話#a會插入a的文字文字,但是多重#做什麼?這個預處理器的東西來了這個。

template<class Ret BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)> 
    typename boost::mpl::if_<boost::is_void<Ret> 
      , luabind::detail::proxy_function_void_caller<boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > 
      , luabind::detail::proxy_function_caller<Ret, boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > >::type 
    call_function(lua_State* L, const char* name BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS, _)) 
    { 
     typedef boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> tuple_t; 
#if BOOST_PP_ITERATION() == 0 
     tuple_t args; 
#else 
     tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a)); 
#endif 

    } 

正如你可以看到它大量使用Boost。我搜索了BOOST_PP_ITERATION,但仍然無法確定它正在做什麼。有人可以請我解釋一下,最好是在這段代碼的背景下,BOOST_PP的東西在做什麼,以及它如何設法將參數置入args

我的最終目標是在自己的代碼中定義一個call_function,該代碼將生成args,我可以將其傳遞給我將定義的call_function的重載。這意味着我可以使用相同的調用約定,但也可以在調用luabind之前應用一些預處理。

這個問題在我的措辭中非常具體,但是我希望這些概念足夠普遍,因爲它在這裏是可以接受的。

+0

你應該看看[Boost.Preprocessor](http://www.boost.org/doc/libs/1_52_0/libs/preprocessor/doc/index.html)文檔 – TemplateRex

回答

3

BOOST_PP_ *與模板元編程無關,它是一個預處理器庫。就像這個名字所說的那樣,它正在處理預處理器的魔法,做一些真正的腦力扭曲的事情來生成一堆類似的模板。在你的情況,這將是以下幾點:

//preprocessor iteration 0 
template<class Ret> 
    typename boost::mpl::if_<boost::is_void<Ret> 
      , luabind::detail::proxy_function_void_caller<boost::tuples::tuple<> > 
      , luabind::detail::proxy_function_caller<Ret, boost::tuples::tuple<> > >::type 
    call_function(lua_State* L, const char* name) 
    { 
     typedef boost::tuples::tuple<> tuple_t; 
     tuple_t args; 
    } 

//preprocessor iteration 1 
template<class Ret , class A0> 
typename boost::mpl::if_<boost::is_void<Ret> 
     , luabind::detail::proxy_function_void_caller<boost::tuples::tuple<const A0 *> > 
     , luabind::detail::proxy_function_caller<Ret, boost::tuples::tuple<const A0 *> > >::type 
call_function(lua_State* L, const char* name , const A0 & a0) 
{ 
    typedef boost::tuples::tuple<const A0 *> tuple_t; 
    tuple_t args(&a0); 
} 

等,多達(A0, A1, A2, A3... A9如果最大爲10例)別處定義一些最大

##是預處理器令牌串聯,在這種情況下,無論值n(=> A0,A1,A2,...)如何級聯A(或a)。整個代碼在一些預處理循環中。

  • BOOST_PP_ITERATION()給出當前循環索引(0,1,2 ...)
  • BOOST_PP_COMMA_IF(X)給人以逗號,如果參數不爲0,例如在模板參數列表中的迭代1中的「A0類」之前的逗號給出逗號分隔的B(?,N,C)列表,其中N從0 ...(n-1)開始,即宏B被執行n次,所以調用BOOST_PP_ENUM(3,LUABIND_TUPLE_PARAMS,_)給出const A0 *, const A1 *, const A2 *
  • BOOST_PP_ENUM_PARAMS(n, X)給出X ## n的逗號分隔列表,例如&a0, &a1, &a2BOOST_PP_ENUM_PARAMS(3, &a)

許多用例爲預處理器魔法可以使用可變參數模板來完成這些天,所以如果你是幸運的,你也不會在這些東西再來;)這是不容易在第一眼就抓住,因爲預處理不像其他已知的C++特性那樣工作,並且有一些必須解決的限制,使得它更不容易理解。