gpt4 book ai didi

c++ - BOOST_PP_ITERATION 可变长度参数

转载 作者:太空狗 更新时间:2023-10-29 21:25:18 25 4
gpt4 key购买 nike

我想将 luabind 合并到我的一个项目中。为此,我需要提供一个行为类似于 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 之前应用一些预处理。

从我的措辞来看,这个问题非常具体,但我希望这些概念足够笼统,可以在这里解决。

最佳答案

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)

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

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

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

关于c++ - BOOST_PP_ITERATION 可变长度参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14273192/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com