MSVC 可変個引数マクロ拡張: 基本と回避策
C プログラミングの領域では、マクロ拡張は、マクロを操作するための強力なツールとなり得ます。そしてオンザフライでコードを生成します。ただし、すべてのコンパイラが可変個の引数を許可する可変個引数マクロを同じ方法で処理できるわけではありません。特に、Microsoft の Visual C (MSVC) コンパイラは、このようなマクロに関しては独特の動作をします。
問題: 意図しない引数の連結
次のように定義された可変長引数マクロについて考えてみましょう。 GCC では次のようになります:
<code class="c++">#define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1)</code>
このマクロは、渡される引数の数をカウントすることを目的としています。ただし、GCC で展開すると、各引数が個別に正しく処理され、必要な数が得られます。ただし、 MSVC では、すべての引数が 1 つの引数に連結されます。
回避策: ネストされたマクロとオーバーロード
MSVC で可変個引数マクロ展開を実現するには、以下を使用できます。これは、マクロのネストとオーバーロードを伴う手法です。次のコードは、このアプローチを示しています。
<code class="c++">#define GLUE(x, y) x y #define RETURN_ARG_COUNT(_1_, _2_, _3_, _4_, _5_, count, ...) count #define EXPAND_ARGS(args) RETURN_ARG_COUNT args #define COUNT_ARGS_MAX5(...) EXPAND_ARGS((__VA_ARGS__, 5, 4, 3, 2, 1, 0)) #define OVERLOAD_MACRO2(name, count) name##count #define OVERLOAD_MACRO1(name, count) OVERLOAD_MACRO2(name, count) #define OVERLOAD_MACRO(name, count) OVERLOAD_MACRO1(name, count) #define CALL_OVERLOAD(name, ...) GLUE(OVERLOAD_MACRO(name, COUNT_ARGS_MAX5(__VA_ARGS__)), (__VA_ARGS__))</code>
使用例:
この回避策を使用すると、コンパイラ間で一貫して動作する可変個引数マクロを定義できます。たとえば、次のエラー レポート マクロ:
<code class="c++">#define ERROR(...) CALL_OVERLOAD(ERROR, __VA_ARGS__)</code>
は、可変数の引数でエラーを出力するために使用できます:
<code class="c++">ERROR("Error: %s", errorMessage); // single argument ERROR("Error: %s", errorMessage, "Additional details"); // two arguments</code>
Key Insights:
以上がMSVC で可変個引数マクロ展開を実現するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。