- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我想将 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/
为什么禁用类型像 type t = A of int | B of string * mutable int 虽然允许此类类型: type t = A of int | B of string * i
我正在寻找一种类似结构的数据结构,我可以从中创建多个实例并具有某种类型提示而不是不可变的。 所以我有这样的东西: class ConnectionConfig(NamedTuple): nam
我需要转到引用的结构: class SearchKnot { var isWord : Bool = false var text : String = "" var to
如sec 10.4.3中所述 当控制进入执行时,执行以下步骤 功能对象F(调用者)中包含的功能代码的上下文 提供thisArg,而调用方提供argumentsList: 如
i make a game that start display Activity indicator And activity indicator bottom display UiLable wi
编辑:我在这里不断获得支持。只是为了记录,我认为这不再重要。自从我发布它以来我就不再需要它了。 我想在 Scala 中执行以下操作... def save(srcPath: String, destP
使用可变对象作为 Hashmap 键是一种不好的做法吗?当您尝试使用已修改足以更改其哈希码的键从 HashMap 中检索值时,会发生什么? 例如,给定 class Key { int a; /
如果您在Kotlin中访问List类型的Java值,则将获得(Mutable)List!类型。 例如。: Java代码: public class Example { public stati
我编写了 str 类(内置)的以下扩展,以便执行以下操作:假设我有字符串 "Ciao" ,通过做"Ciao" - "a"我想要的结果是字符串 "Cio" 。这是执行此操作的代码,并且运行良好: cla
使用可变对象作为 Hashmap 键是一种不好的做法吗?当您尝试使用已修改足以更改其哈希码的键从 HashMap 中检索值时,会发生什么? 例如,给定 class Key { int a; /
我正在为我的公司设计一个数据库来管理商业贷款。每笔贷款都可以有担保人,可以是个人或公司,在借款业务失败时作为财务支持。 我有 3 个表:Loan、Person 和 Company,它们存储明显的信息。
我使用二进制序列化从 C# 类中保存 F# 记录。一切正常: F#: type GameState = { LevelStatus : LevelStatus
import javax.swing.JOptionPane; public class HW { public static void main(String[] args) { Strin
使用 flatbuffer mutable 有多少性能损失? 是否“正确”使用 FlatBuffers 来拥有一个应该可编辑的对象/结构(即游戏状态) 在我的示例中,我现在有以下类: class Ga
std::function create_function (args...) { int x = initial_value (args...); return [x] () mut
我需要在 for 循环中找到用户输入的字符。我通常会这样做 如果(句子[i] == 'e') 但是因为在这里,'e' 将是一个单字母字符变量,我不知道如何获取要比较的值。我不能只输入 if (sent
我有一个这样的算法: let seed: Foo = ... let mut stack: Vec = Vec::new(); stack.push(&seed); while let Some(ne
这个问题可能看起来非常基础,但我很难弄清楚如何做。我有一个整数,我需要使用 for 循环来循环整数次。 首先,我尝试了—— fn main() { let number = 10; // An
如果我有以下结构: struct MyStruct { tuple: (i32, i32) }; 以及以下函数: // This will not compile fn function(&mut s
我希望在每个 session 的基础上指定列的默认值。下面的脚本不起作用,但描述了我想如何使用它。我目前使用的是 MySQL 5.5.28,但如果需要可以升级。 CREATE TABLE my_tbl
我是一名优秀的程序员,十分优秀!