首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >可变长度参数的BOOST_PP_ITERATION

可变长度参数的BOOST_PP_ITERATION
EN

Stack Overflow用户
提问于 2013-01-11 14:54:44
回答 1查看 934关注 0票数 3

我想把一个luabind整合到我的一个项目中。为此,我需要提供一个行为类似于call_function的函数(见下文)。这个函数使用了一些模板魔法(由Boost提供),我希望能得到一些帮助。这是我第一次真正接触到模板元编程(这就是它的名字吗?)所以我有点迷路了。这里有一些我希望得到帮助的代码片段。

代码语言:javascript
复制
#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的文本,但是多个#做什么呢?在这个预处理器的东西之后是这样的。

代码语言:javascript
复制
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之前应用一些预处理。

这个问题在我的表达方式中是非常具体的,但我希望概念足够通用,以便在这里可以。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-01-11 16:09:07

BOOST_PP_*与模板元编程无关,它是一个预处理器库。正如它的名字所说,它使用预处理器魔法,做一些非常复杂的事情来生成一堆类似的模板。在您的情况下,这将是以下情况:

代码语言:javascript
复制
//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);
}

以此类推,直到其他地方定义的某个最大值(例如,如果最大值为10,则为A0, A1, A2, A3... A9 )

##是预处理器的标记连接,在本例中,连接A(或a)和任何值n (=> A0,A1,A2,...)。整个代码都在某个预处理循环中。

  • BOOST_PP_ITERATION()给出当前循环索引(0,1,如果自变量不是0,则2...)
  • BOOST_PP_COMMA_IF(X)给出一个逗号,例如,在模板参数list
  • BOOST_PP_ENUM(n,B,C)中的迭代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列表,例如,用于BOOST_PP_ENUM_PARAMS(3, &a)

&a0, &a1, &a2

如今,预处理器的许多用例都可以使用可变模板完成,所以如果幸运的话不会再遇到这种东西;)乍一看并不容易掌握,因为预处理不像其他已知的C++特性那样工作,并且有一些必须解决的限制,这使得它更不容易理解。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14273192

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档