4

FOR_EACH可変個引数マクロのバリエーションを求めるいくつかの質問を見てきました。ただし、残念ながら、提供された回答は、別のマクロに渡されたときに1つの引数として__VA_ARGS __を展開するため、VC++10と互換性がありません。誰かがVC++10でまだ機能するC++11準拠(したがって上位互換)バージョンを提供してくれませんか。よく言われる「回避策」を使用しているかもしれませんが、たとえば、この回答の後者の一般化された部分をVC ++ 10で機能#define EXPAND(x) xさせるために、これをどこに置くかはわかりません。

明確にするために、意図された動作は、FOR_EACH(x, a, b, ...)を生成することx(a) x(b), ...です。ここで、xは別のマクロです。

4

2 に答える 2

8

VC ++ 10コンパイラのバグがどのように機能するかを正確に把握したので、この回答の後半に基づいて、このようなマクロを自分で思いつくことができました。

#define EXPAND(x) x
#define FOR_EACH_1(what, x, ...) what(x)
#define FOR_EACH_2(what, x, ...)\
  what(x);\
  EXPAND(FOR_EACH_1(what,  __VA_ARGS__))
#define FOR_EACH_3(what, x, ...)\
  what(x);\
  EXPAND(FOR_EACH_2(what, __VA_ARGS__))
#define FOR_EACH_4(what, x, ...)\
  what(x);\
  EXPAND(FOR_EACH_3(what,  __VA_ARGS__))
#define FOR_EACH_5(what, x, ...)\
  what(x);\
  EXPAND(FOR_EACH_4(what,  __VA_ARGS__))
#define FOR_EACH_6(what, x, ...)\
  what(x);\
  EXPAND(FOR_EACH_5(what,  __VA_ARGS__))
#define FOR_EACH_7(what, x, ...)\
  what(x);\
  EXPAND(FOR_EACH_6(what,  __VA_ARGS__))
#define FOR_EACH_8(what, x, ...)\
  what(x);\
  EXPAND(FOR_EACH_7(what,  __VA_ARGS__))
#define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__, FOR_EACH_RSEQ_N())
#define FOR_EACH_NARG_(...) EXPAND(FOR_EACH_ARG_N(__VA_ARGS__))
#define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N
#define FOR_EACH_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0
#define CONCATENATE(x,y) x##y
#define FOR_EACH_(N, what, ...) EXPAND(CONCATENATE(FOR_EACH_, N)(what, __VA_ARGS__))
#define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__)

使用例:

#define callMember(o, f) o.f();
#define callMember_o(f) callMember(o, f)
FOR_EACH(callMember_o, doSomething, doSomethingElse);

と同じです

o.doSomething(); o.doSomethingElse();

この解決策はリンクされた回答の解決策と似ていますが、FOR_EACH(what, x, ...)1つの要素で呼び出されたときに長さがゼロの可変引数リストが偽のコンマを引き起こし、FOR_EACH_NARGが1つの引数ではなく2つの引数をカウントし、EXPANDマクロの回避策が使用される点が異なります。

VC ++ 10のバグは__VA_ARGS__、可変個引数マクロの定義内のマクロに渡された場合、マクロへの置換後に評価され、複数のコンマ区切りの引数が1つとして扱われることです。これを回避するに__VA_ARGS__は、マクロ呼び出しをでラップし、マクロ呼び出しEXPANDを文字列として評価するように強制し、置換__VA_ARGS__することにより、引数の評価を置換されるまで遅らせる必要があります。への置換後にのみEXPANDマクロが呼び出され、その時点で可変個引数はすでに置換されています。

FOR_EACH_NPSの値がはるかに大きいマクロをコンパクトに作成する方法を誰かが提案できれば幸いですN

于 2013-02-06T17:25:20.040 に答える
1

Dylanの回答に基づいて、for_eachマクロをN回生成するPythonコードを作成しました。

以下はコードです:

from builtins import *

# number of generated for_each cases.
iter_max = 19

# override this with your own!
prefix = "MY_"  # define your own macro prefix, which ends with under_score if not empty.
internal_prefix = "internal_"

# CODE ------------------------------------------------------------------------------------------------------
INTERNAL_ = f"{internal_prefix}{prefix}"

fmt_numstr = "{}"  # f"{{:0>{max_digit}}}"

EXPAND = f"{INTERNAL_}EXPAND"

FOR_EACH = f"{INTERNAL_}FOR_EACH_"
FOR_EACH_N = f"{FOR_EACH}{fmt_numstr}"

OUT = "#pragma once\n"

OUT += f"#define {EXPAND}(x) x\n"
OUT += f"#define {FOR_EACH_N.format(1)}(what, x, ...) what(x)\n"

for i in range(2, iter_max + 1):
    OUT += f"#define {FOR_EACH_N.format(i)}(what, x, ...) " \
           f"what(x);" \
           f"{EXPAND}({FOR_EACH_N.format(i - 1)}(what, __VA_ARGS__))\n"

FOR_EACH_NARG = f"{INTERNAL_}FOR_EACH_NARG"
FOR_EACH_RSEQ_N = f"{INTERNAL_}FOR_EACH_RSEQ_N"
FOR_EACH_ARG_N = f"{INTERNAL_}FOR_EACH_ARG_N"

OUT += f"#define {FOR_EACH_NARG}(...) {FOR_EACH_NARG}_(__VA_ARGS__, {FOR_EACH_RSEQ_N}())\n"
OUT += f"#define {FOR_EACH_NARG}_(...) {EXPAND}({FOR_EACH_ARG_N}(__VA_ARGS__))\n"

underscore_sequence = ""
inverse_sequence = ""
for i in range(1, iter_max + 1):
    underscore_sequence += f"_{i}{',' if i < iter_max else ''}"

for i in range(0, iter_max + 1):
    inverse_sequence += f"{fmt_numstr}{',' if i < iter_max else ''} ".format(iter_max - i)

OUT += f"#define {FOR_EACH_ARG_N}({underscore_sequence}, N, ...) N\n"
OUT += f"#define {FOR_EACH_RSEQ_N}() {inverse_sequence}\n"

CONCATENATE = f"{INTERNAL_}CONCATENATE"

OUT += f"#define {CONCATENATE}(x,y) x##y\n"

INTERNAL_FOR_EACH = f"{INTERNAL_}FOR_EACH_"

OUT += f"#define {INTERNAL_FOR_EACH}(N, what, ...) {EXPAND}({CONCATENATE}({FOR_EACH}, N)(what, __VA_ARGS__))\n"
OUT += f"#define {prefix}FOR_EACH(what, ...) {INTERNAL_FOR_EACH}({FOR_EACH_NARG}(__VA_ARGS__), what, __VA_ARGS__)\n"

print(OUT)

実行結果は次のとおりです。

#pragma once
#define internal_MY_EXPAND(x) x
#define internal_MY_FOR_EACH_1(what, x, ...) what(x)
#define internal_MY_FOR_EACH_2(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_1(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_3(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_2(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_4(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_3(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_5(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_4(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_6(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_5(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_7(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_6(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_8(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_7(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_9(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_8(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_10(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_9(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_11(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_10(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_12(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_11(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_13(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_12(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_14(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_13(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_15(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_14(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_16(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_15(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_17(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_16(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_18(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_17(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_19(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_18(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_NARG(...) internal_MY_FOR_EACH_NARG_(__VA_ARGS__, internal_MY_FOR_EACH_RSEQ_N())
#define internal_MY_FOR_EACH_NARG_(...) internal_MY_EXPAND(internal_MY_FOR_EACH_ARG_N(__VA_ARGS__))
#define internal_MY_FOR_EACH_ARG_N(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19, N, ...) N
#define internal_MY_FOR_EACH_RSEQ_N() 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 
#define internal_MY_CONCATENATE(x,y) x##y
#define internal_MY_FOR_EACH_(N, what, ...) internal_MY_EXPAND(internal_MY_CONCATENATE(internal_MY_FOR_EACH_, N)(what, __VA_ARGS__))
#define MY_FOR_EACH(what, ...) internal_MY_FOR_EACH_(internal_MY_FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__)

自分で使用するために、マクロプレフィックスと内部プレフィックスをカスタマイズできます。

于 2022-01-10T13:18:27.210 に答える