3

我想将 aluabind合并到我的一个项目中。为此,我需要提供一个行为类似于call_function(见下文)的函数。这个函数使用了一些模板魔法(由 Boost 提供),我希望能得到一些帮助。这是我第一次真正遇到模板元编程(这就是所谓的吗?)所以我有点迷茫。这里有一些片段我会很感激帮助。

#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

这个问题在我的措辞上非常具体,但我希望这些概念足够笼统,可以在这里使用。

4

1 回答 1

3

BOOST_PP_* ist not related to template metaprogramming, its a preprocessor library. Like the name says, it's working with preprocessor magic, doing some really braintwisting things to generate a bunch of similar templates. In your case, that would be the following:

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

and so on, up to some maximum defined elsewhere (e.g. A0, A1, A2, A3... A9 if the maximum is 10)

The ## is a token concatenation for the preprocessor, in this case concatenation A (or a) with whatever value n has (=> A0, A1, A2, ...). The whole code is in some preprocessing loop.

  • BOOST_PP_ITERATION() gives the current loop index (0, 1, 2...)
  • BOOST_PP_COMMA_IF(X) gives a comma, if the argument is not 0, e.g. the comma before "class A0" in iteration 1 in the template parameter list
  • BOOST_PP_ENUM(n,B,C) gives a comma separated list of B(?, N, C), where N runs from 0..(n-1), i.e. the macro B gets executed n times, so calling BOOST_PP_ENUM(3, LUABIND_TUPLE_PARAMS, _) gives const A0 *, const A1 *, const A2 *
  • BOOST_PP_ENUM_PARAMS(n, X) gives a comma separated list of X##n, e.g. &a0, &a1, &a2 for BOOST_PP_ENUM_PARAMS(3, &a)

Many of the use cases for that Preprocessor magic can be done with variadic templates these days, so if you are lucky you will not come across that stuff again ;) It's not easy to grasp at first sight, because preprocessing does not work like other known C++ features and has some limitations that one has to work around, making it even less easy to understand.

于 2013-01-11T08:09:06.550 回答