3

作为问题的一个例子,有没有办法partialconcat在下面的代码中实现宏?

#define apply(f, x) f(x)

apply(partialconcat(he),llo) //should produce hello

编辑:

这是另一个示例,给定一个可变参数宏(请参阅this answer to another questionFOR_EACH中的示例实现)。

假设我想在多个对象上调用一个成员,可能在另一个宏中用于更大的目的。我想要一个行为如下的宏 callMember:

FOR_EACH(callMember(someMemberFunction), a, b, c);

生产

a.someMemberFunction(); b.someMemberFunction(); c.someMemberFunction();

这需要callMember(someMember)产生一个行为类似的宏

#define callMember_someMember(o) o.someMember()
4

3 回答 3

5

您可以使用 Vesa Karvonen 令人难以置信的“秩序”语言/库通过预处理器获得所需的结果: http ://rosettacode.org/wiki/Order

这是通过在预处理器本身之上实现完整的第二种高级语言来实现的,支持诸如柯里化和一流的宏等。虽然它非常繁重,但重要的 Order 代码需要很长时间才能编译,因为 CPP 的设计目的不是以这种方式使用,而且大多数 C 编译器都无法处理它。它也非常脆弱:输入代码中的错误往往会产生难以理解的乱码输出。

但是,是的,它可以完成,并且在一次预处理程序中完成。它比您预期的要复杂得多

于 2013-02-11T00:24:25.700 回答
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();

由于它是一个编译时循环,因此很难进行柯里化。该OBJECT_LIST宏定义了允许此列表的每个用户柯里化的参数数量。(默认)函数调用参数是定义的一部分。您可以自由选择不使用默认提供的参数或自己使用常量值。我无法找到减少预处理器中参数数量的适当方法。这一事实限制了该技术的普遍性。

#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);
于 2014-07-17T08:17:25.780 回答
1

C 预处理器“只是”一个简单的文本处理器。特别是,一个宏不能定义另一个宏;您不能#define从宏的扩展中创建一个。

我认为这意味着您问题的最后两行:

这需要callMember(someMember)产生一个行为类似的宏

#define callMember_someMember(o) o.someMember()

使用 C 预处理器的单个应用程序是无法实现的(并且,在一般情况下,您需要应用预处理器任意次数,具体取决于宏的定义方式)。

于 2013-02-06T18:01:27.140 回答