13

可変個引数に引数を指定せずに可変個引数マクロを呼び出すことは合法Mですか?

関連する標準引用符は[cpp.replace]/4です:

マクロ定義の識別子リストが省略記号で終わらない場合、関数のようなマクロの呼び出しにおける引数の数 (前処理トークンを含まない引数を含む) は、マクロ定義のパラメーターの数と等しくなければなりません。それ以外の場合、呼び出しには、マクロ定義のパラメーターよりも多くの引数が必要です ( を除く...)。)呼び出しを終了する前処理トークンが存在する必要があります。

非可変長パラメーターがない場合M()、呼び出しには 1 つの引数 (前処理トークンで構成されていない) があるため、フォーム内の呼び出しは正当である必要があります。したがって、非可変引数よりも引数が 1 つ多くなります。

非可変引数が 1 つの場合、可変引数の前処理トークンを含まない引数を導入するために末尾,に as を付ける必要がありますか? M(1,)それ以外の場合、引数の数は非可変引数の数と等しくなります。つまり、

#define variadic(x,...) #__VA_ARGS__

variadic(1,) // 2 arguments: ok
variadic(1) // 1 argument: wrong?

ただし、 ClangGCCはどちらも次のテスト ケースを受け入れます。

#include <iostream>

#define variadic(x,...) #__VA_ARGS__

int main()
{
    std::cout << "'" variadic(1) "'" << std::endl;
}

そして出力として生成します:

''

これは標準外の動作ですか?

4

1 に答える 1

8

それ以外の場合、呼び出しには、マクロ定義のパラメーターよりも多くの引数が必要です (... を除く)。

この標準からの抜粋は、コードが有効であってはならないことを示しています。1 つのパラメーターと省略記号があります。上記の標準の部分に従う場合、少なくとも 2 つの引数が必要です。を記述するときはvaridadic(1)、引数を 1 つだけ指定します。あなたのコードは無効です。

ところで、clang は次の警告を生成します。

main.cpp:7:32: warning: must specify at least one argument for '...' parameter of variadic macro [-Wgnu]
    std::cout << "'" variadic(1) "'" << std::endl;

また、GCC も警告を生成します。

main.cpp:7:32: warning: ISO C99 requires rest arguments to be used [enabled by default]
     std::cout << "'" variadic(1) "'" << std::endl;

それはプログラマーにとって煩わしいかもしれませんし、プログラマーの意図は推測されやすいので、両者はvariadic(1)が と同等であると考えvariadic(1,)ます。

于 2013-05-27T08:30:23.977 に答える