作为问题的一个示例,有没有办法在以下代码中实现宏partialconcat
?
#define apply(f, x) f(x)
apply(partialconcat(he),llo) //should produce hello
编辑:
这是另一个例子,给定一个FOR_EACH
可变参数宏(参见this answer中另一个问题的示例实现)。
说我想在几个对象上调用成员, 可能在另一个宏中用于更大的目的。 我想要一个宏callAmber,其行为如下:
FOR_EACH(callMember(someMemberFunction), a, b, c);
产生
a.someMemberFunction(); b.someMemberFunction(); c.someMemberFunction();
这需要callMember(someMember)
来生成一个行为类似于
#define callMember_someMember(o) o.someMember()
答案 0 :(得分:5)
使用Vesa Karvonen令人难以置信的“订购”语言/库,您可以使用预处理器实现所需的结果:http://rosettacode.org/wiki/Order
这可以通过在预处理器本身的之上实现第二个高级语言来实现,并支持currying和一流宏等等。这是非常繁重的,但非常重要的Order代码需要很长时间才能编译,因为CPP并不是以这种方式设计的,而且大多数C编译器都无法处理它。它也非常脆弱:输入代码中的错误往往会产生难以理解的乱码输出。
但是,是的,它可以完成,并在一个预处理器传递中完成。它只是一个很多比你想象的更复杂。
答案 1 :(得分:2)
使用更高阶的宏:
#define OBJECT_LIST(V) \
V(a) \
V(b) \
V(c)
#define MEMBER_CALL(X) \
X.some_func();
OBJECT_LIST(MEMBER_CALL)
<强>输出强>
$ g++ -E main.cc
# 1 "main.cc"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main.cc"
# 10 "main.cc"
a.some_func(); b.some_func(); c.some_func();
因为它是一个编译时循环,所以很难进行curry。 OBJECT_LIST
宏定义了允许此列表的每个用户进行咖喱的参数数量。 (默认)函数调用参数是define的一部分。您可以自由选择不使用默认提供的参数或自己使用常量值。我无法找到减少预处理器中参数数量的正确方法。这一事实限制了这种技术的普遍性。
#define OBJECT_LIST(V) \
V(a, 1,2,3) \
V(b, 4,5,6)
#define MEMBER_CALL(X, A1, A2, A3) \
X.somefunc(A1, A2, A3);
#define CURRY_CALL(X, A1, A2, A3) \
X.somefunc(A1, 2, 2);
#define NO_CURRY_CALL(X, A1, A2, A3) \
X.xomefunc(A1);
OBJECT_LIST(MEMBER_CALL)
OBJECT_LIST(CURRY_CALL)
OBJECT_LIST(NO_CURRY_CALL)
<强>输出:强>
# 1 "main2.cc"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main2.cc"
# 12 "main2.cc"
a.somefunc(1, 2, 3); b.somefunc(4, 5, 6);
a.somefunc(1, 2, 2); b.somefunc(4, 2, 2);
a.somefunc(1); b.somefunc(4);
答案 2 :(得分:1)
C预处理器“仅”是一个简单的文本处理器。特别是,一个宏不能定义另一个宏;你无法通过扩展宏来创建#define
。
我认为这意味着问题的最后两行:
使用C预处理器的单个应用程序无法实现这需要
的宏callMember(someMember)
来生成一个行为类似于
#define callMember_someMember(o) o.someMember()
(在一般情况下,您需要将预处理器应用任意次数,具体取决于宏的定义方式。)