2016-03-24 7 views
2

for-loopsをシミュレートしてコピーと貼り付けコードを排除するC++マクロコードです。FOR_EACHマクロ(呼び出しマクロ内に2つ以上のパラメータがある)

#define SEMICOLON ; 
#define LOL(x) print(x) 
#define LOLZ(...) FOR_EACH(LOL, SEMICOLON, ##__VA_ARGS__) 

LOLZ("hi", "my", "friend", "!"); 

// result 
print("hi"); print("my"); print("friend"); print("!"); 

そしてまた、私は、このマクロを作成するためのコードを表示することができます(私はこのhere on Stack Overflowを見つけた):

#define EXPAND(x) x 
#define FOR_EACH_1(what, delimiter, x, ...) what(x) 
#define FOR_EACH_2(what, delimiter, x, ...)\ 
    what(x) delimiter \ 
    EXPAND(FOR_EACH_1(what, delimiter, __VA_ARGS__)) 
#define FOR_EACH_3(what, delimiter, x, ...)\ 
    what(x) delimiter \ 
    EXPAND(FOR_EACH_2(what, delimiter, __VA_ARGS__)) 
#define FOR_EACH_4(what, delimiter, x, ...)\ 
    what(x) delimiter \ 
    EXPAND(FOR_EACH_3(what, delimiter, __VA_ARGS__)) 
#define FOR_EACH_5(what, delimiter, x, ...)\ 
    what(x) delimiter \ 
    EXPAND(FOR_EACH_4(what, delimiter, __VA_ARGS__)) 
#define FOR_EACH_6(what, delimiter, x, ...)\ 
    what(x) delimiter \ 
    EXPAND(FOR_EACH_5(what, delimiter, __VA_ARGS__)) 
#define FOR_EACH_7(what, delimiter, x, ...)\ 
    what(x) delimiter \ 
    EXPAND(FOR_EACH_6(what, delimiter, __VA_ARGS__)) 
#define FOR_EACH_8(what, delimiter, x, ...)\ 
    what(x) delimiter \ 
    EXPAND(FOR_EACH_7(what, delimiter, __VA_ARGS__)) 
#define FOR_EACH_9(what, delimiter, x, ...)\ 
    what(x) delimiter \ 
    EXPAND(FOR_EACH_8(what, delimiter, __VA_ARGS__)) 
#define FOR_EACH_10(what, delimiter, x, ...)\ 
    what(x) delimiter \ 
    EXPAND(FOR_EACH_9(what, delimiter, __VA_ARGS__)) 
#define FOR_EACH_11(what, delimiter, x, ...)\ 
    what(x) delimiter \ 
    EXPAND(FOR_EACH_10(what, delimiter, __VA_ARGS__)) 
#define FOR_EACH_12(what, delimiter, x, ...)\ 
    what(x) delimiter\ 
    EXPAND(FOR_EACH_11(what, delimiter, __VA_ARGS__)) 
#define FOR_EACH_13(what, delimiter, x, ...)\ 
    what(x) delimiter \ 
    EXPAND(FOR_EACH_12(what, delimiter, __VA_ARGS__)) 
#define FOR_EACH_14(what, delimiter, x, ...)\ 
    what(x) delimiter \ 
    EXPAND(FOR_EACH_13(what, delimiter, __VA_ARGS__)) 
#define FOR_EACH_15(what, delimiter, x, ...)\ 
    what(x) delimiter \ 
    EXPAND(FOR_EACH_14(what, delimiter, __VA_ARGS__)) 
#define FOR_EACH_16(what, delimiter, x, ...)\ 
    what(x) delimiter \ 
    EXPAND(FOR_EACH_15(what, delimiter, __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, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) N 
#define FOR_EACH_RSEQ_N() 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 
#define CONCATENATE(x,y) x##y 
#define FOR_EACH_(N, what, delimiter, ...) EXPAND(CONCATENATE(FOR_EACH_, N)(what, delimiter, __VA_ARGS__)) 


#define FOR_EACH(what, delimiter, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, delimiter, __VA_ARGS__) 

しかし、私は機能のための2つの引数を持つ難しあります を私はFUNC(Xを使用する必要があります、y)を返します。

func(x1, y1); func(x2, y2); func(x3, y3); func(,); func(,); func(,); 

場合:私は、私が「何を」引数を呼び出すのX2 unsed置換を得ただろうマクロで「×」引数の近くに「y」を追加した場合

MY_DUAL_FOREACH_LIKE_MACRO(
    x1, y1, 
    x2, y2, 
    x3, y3 
) 

// and I expect to get: 
func(x1, y1); func(x2, y2); func(x3, y3); 

: 呼び出すマクロは次のようになりますなければなりませんあなたはこれを経験しています。私はこのマクロをデュアル引数型FOR_EACHマクロにコード化するのを手伝ってください。

+3

私はこれを行うことをお勧めしません。どのような問題を解決しようとしていますか?構造内のデータを表現し、それを反復することでそれを解決できますか? – TartanLlama

+4

マクロは悪です。私はそのようなコードを決してデバッグしないことを望む。 Btw。この「二重」反復は、zip iteratorと呼ばれ、ブーストライブラリにあります。 – Radek

+1

"答えの1つでスタックのオーバーフローでこれが見つかりました"ソースにリンクしてください。 –

答えて

3

私の判断に反して、私はこれに答えるつもりです(これはほんの稀なケースで役に立ちます)。私はあなたがそれを2つのパラメータ(demo)を必要と掲載コードを変更:

#include <iostream> 

#define EXPAND(x) x 
#define FOR_EACH_2(what, delimiter, x, y) what((x), (y)) 
#define FOR_EACH_4(what, delimiter, x, y, ...)\ 
    what((x), (y)) delimiter \ 
    EXPAND(FOR_EACH_2(what, delimiter, __VA_ARGS__)) 
#define FOR_EACH_6(what, delimiter, x, y, ...)\ 
    what((x), (y)) delimiter \ 
    EXPAND(FOR_EACH_4(what, delimiter, __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, N, ...) N 
#define FOR_EACH_RSEQ_N() 6, 5, 4, 3, 2, 1, 0 
#define CONCATENATE(x,y) x##y 
#define FOR_EACH_(N, what, delimiter, ...) EXPAND(CONCATENATE(FOR_EACH_, N)(what, delimiter, __VA_ARGS__)) 

#define FOR_EACH(what, delimiter, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, delimiter, __VA_ARGS__) 

void foo(int x, float y) { 
    std::cout << "foo(" << x << ", " << y << ")\n"; 
} 

int main() { 
    FOR_EACH(foo, ;, 1, 3.14, 2, 1.41, 3, 1.73); 
} 

出力は次のとおりです。

foo(1, 3.14) 
foo(2, 1.41) 
foo(3, 1.73) 

あなたが3倍以上foo多くを呼び出したい場合は、追加の例を追加する必要があります私は読者に運動として残します。

これはクリーンアップすることができます。FOR_EACH(おそらくFOR_EACH_2のように2つの引数で同時に動作することを示す)とは別の名前を付ける必要があります。

私が読者に練習として残しているのは、この回答の使用を阻止することですが、それを完全に防ぐわけではありません。あなたがこれをきれいにして、それをあなたの必要に合わせて調整するのに気にすることができないなら、それはあなたの上にあります。

+0

ありがとう!私はほとんど推測しました!しかし、どのラウンドブラケット? (何(x)、(y)) – Broly

+2

@ブロッ:[このような狂気を抑える](http://ideone.com/WwdP4M)。詳細については、[このような質問](http://stackoverflow.com/q/7186504/1287251)を参照してください。 – Cornstalks

1

マクロ引数をカッコでグループ化すると、各グループは1つの引数として扱われます。それは次のように呼び出すことができるように、あなたはおそらくマクロを変更できます。

MY_DUAL_FOREACH_LIKE_MACRO(
    (x1, y1), 
    (x2, y2), 
    (x3, y3) 
) 

その後一緒にマクロペーストfunc(x1, y1)を持っています。

+0

ありがとう、私はそれを試してみる:) – Broly

2

通常、理由のために解決策が選択されたと仮定して、質問に答えようとします。しかし、私は21世紀のC++でのマクロの使用についてかなり強い意見を持っていますので、私はこれを回答として投稿しています。


してください、くださいは、このようなマクロを乱用しないでください。ご希望の場合は、

std::vector<std::pair<double, double>> values = { 
    { x1, y1 }, 
    { x2, y2 }, 
    { x3, y3 } 
}; 

for(auto& pair : values) 
{ 
    f(pair.first, pair.second); 
} 

あなたはまた、1つのベクターにそれらを置くことができます:

それはあなたがここにマクロなしで完全に受け入れ、読みやすい、デバッグ、保守性ソリューションであり、引数のペアで関数を呼び出したいです:

std::vector<double> values = { 
    x1, y1, 
    x2, y2, 
    x3, y3 
}; 

for(int i = 0; i < values.size(); i += 2) 
{ 
    f(values[i], values[i + 1]); 
} 
+0

私はマクロのアプローチが嫌いですが、1つの利点は、メモリを割り当てる/割り当てを解除する必要はありません。 – Cornstalks

+0

あなたの答えをありがとう、私はマクロを乱用することを理解しました。 いくつかのプロセスを自動化する必要があります。これは関数を呼び出すだけではありません。これは型定義とメソッド宣言です。 私がこれを動作させるフレームワークは、これを使用する正当な理由です。 – Broly

+0

@Brolyのように、あなたが必要とするマクロではありませんが、テンプレート – Garf365

関連する問題