2017-10-17 6 views
1

Overloading Macro on Number of Argumentsなぜ私のvariadicマクロは引数を正しく受け入れないでしょうか?

https://codecraft.co/2014/11/25/variadic-macros-tricks/

私は仕事に以下のコードを取得しようと、上記二つのリンクで見てきた:

#define _GET_NUMBER(_0, _1, _2, _3, _4, _5, NAME, ...) NAME 
#define OUTPUT_ARGS_COUNT(...) _GET_NUMBER(_0, ##__VA_ARGS__, 5, 4, 3, 2, 1, 0) 

... 

cout << OUTPUT_ARGS_COUNT("HelloWorld", 1.2) << endl; 
cout << OUTPUT_ARGS_COUNT("HelloWorld") << endl; 
cout << OUTPUT_ARGS_COUNT() << endl; 

これは、コンパイル実行され、次のような出力が得られます。

2 
1 
1 

なぜ私はOUTPUT_ARGS_COUNT()を呼び出すのか理解できません私は使用しようとしているコードをよく理解していますが、まだギリシャ語です。文字通りコピーしたにもかかわらず、何かを正しく適用していない可能性がありますスタックオーバーフロー時にリンクからサンプルコードを貼り付けました。あなたがに私を指すことができ

私はグラムを使用してコンパイルしてい++ 5.4.0 20160609.

任意のアイデアや追加のリソースをいただければ幸いです。あなたはhttp://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.htmlで見ることができます

+1

http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.htmlで見ることができます:* "上記の説明は、唯一のマクロパラメータが可変引数パラメータである場合についてあいまいです何も引数が空の引数か不足している引数かどうかを区別しようとするのは無意味ですCPPは特定のC標準に準拠しているときはカンマを保持し、それ以外の場合は標準への拡張として取り除かれます。 – Jarod42

+0

これをチェックしてくださいhttps://stackoverflow.com/questions/2308243/macro-returning-the-number-of-arguments-it-is-given-in-c、解決策はゼロ引数でも失敗します –

答えて

1

マクロ定義内の識別子リストは、[...]、省略記号で終わっていない場合はC標準は

を指定します。それ以外の場合は、マクロ定義内のパラメータが存在するよりも、呼び出しで複数の引数がなければならない(除くが...)

C2011 6.10.3/4;強調を追加)

C++ 11が含まれ16.3/4節で同じ効果を得る。

どちらの場合でも、マクロの呼び出しに引数がないと解釈された場合、プログラムは不適合となります。一方、プリプロセッサは、空のマクロ引数、つまり、前処理トークンがゼロである引数を認識してサポートします。原則として、議論と空の議論のあいだにはあいまいさがありますが、実際には、後者の解釈だけが合致するプログラムになります。

g ++では、後者の解釈を選択しています(もう1つの答えは、その旨の文書を引用しています)。したがって、合理的で適切です。コードを移植したい場合は、それに頼るのは安全ではありません。代わりの解釈をとるコンパイラは、おそらく期待した振る舞いを提供するだけでなく、おそらくコードを拒否することによって、異なる動作をします。

2

:カンマと可変長引数の間に配置されたとき

第二には、「##」トークンペースト演算子は特別な意味を持っています。あなたは

#define eprintf(format, ...) fprintf (stderr, format, ##__VA_ARGS__) 

を書いている場合、可変引数がeprintfマクロを使用する場合に取り残され、その後、「##」の前にカンマが削除されます。これは空の引数を渡しても起こりません。また、 '##'の前のトークンがコンマ以外のものであっても起こりません。まったく引数が空の引数はありませんか欠落しているかどうかを区別しようとすることは無意味であるよう

eprintf ("success!\n") 
→ fprintf(stderr, "success!\n"); 

上記の説明では、唯一のマクロのパラメータは、可変引数パラメータである場合についてあいまいです引数。 CPPは特定のC標準に準拠している場合はカンマを保持します。それ以外の場合は、標準への拡張子としてカンマが削除されます。

だから、(適切な拡張子を使用しない限り)OUTPUT_ARGS_COUNT() 1つの空の引数としてカウントされる(コンマは##__VA_ARGS__で維持しました)。

+0

私はそのドキュメントを見ました私の元の投稿へのあなたのコメントの後に、私はOUTPUT_ARGS_COUNT()を呼び出すときに私は0を得ることができるようにそれに基づいて変更するか分からない。それができないことを示唆していますか?または、おそらく、私はちょうど適切な拡張子が何を参照しているか理解していないだけです。 – Brian

+1

[デモ](http://coliru.stacked-crooked.com/a/090b4438717735c3)で分かるように、 '-std = gnu ++ XX'は' 0'を、 '-std = C++ XX 'は' 1 'を返す。あなたはその構造について明白な警告を得ました。 – Jarod42

+1

@Brian:引用文に記載されているように、それはあなたがコンパイルしている標準バージョンに依存します。例えば ​​'-std = c99'でコンパイルすると、あなたが出力したものが表示されます。一方、 '-std = gnu99'を使うと、' 2 1 0'が得られます。 –

関連する問題