質問

As an example of the problem, is there any way to implement the macro partialconcat in the following code?

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

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

EDIT:

Here's another example, given a FOR_EACH variadic macro (see an example implementation in this answer to another question).

Say I want to call a member on several objects, probably within another macro for a greater purpose. I would like a macro callMember that behaves like this:

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

produces

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

This needs callMember(someMember) to produce a macro that behaves like

#define callMember_someMember(o) o.someMember()
役に立ちましたか?

解決 3

The C preprocessor is 'only' a simple text processor. In particular, one macro cannot define another macro; you cannot create a #define out of the expansion of a macro.

I think that means that the last two lines of your question:

This needs callMember(someMember) to produce a macro that behaves like

#define callMember_someMember(o) o.someMember()

are not achievable with a single application of the C preprocessor (and, in the general case, you'd need to apply the preprocessor an arbitrary number of times, depending on how the macros are defined).

他のヒント

You can achieve the desired result with the preprocessor using Vesa Karvonen's incredible "Order" language/library: http://rosettacode.org/wiki/Order

This works by implementing a whole second high-level language on top of the preprocessor itself, with support for things like currying and first-class macros and so on. It's pretty heavy-duty though, nontrivial Order code takes a very long time to compile because CPP wasn't designed to be used in that way, and most C compilers can't handle it. It's also very fragile: errors in the input code tend to produce incomprehensible gibberish output.

But yes, it can be done, and done in one preprocessor pass. It's just a lot more complicated than you might have been expecting.

Use higher order macros:

#define OBJECT_LIST(V) \
    V(a) \
    V(b) \
    V(c)

#define MEMBER_CALL(X) \
    X.some_func();


OBJECT_LIST(MEMBER_CALL)

output

$ 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();

since it is a compile time loop, currying is difficult. the OBJECT_LIST macro defines how many arguments every user of this list is allowed to curry. the (default) function call arguments are part of the define then. You can freely choose not to use the default supplied argument or use a constant value yourself. I was not able to find a proper way to reduce the amount of arguments in the preprocessor. This fact limits the generality of this technique.

#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)

output:

# 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);
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top