Ok。これは良くありません。しかし、事前に指定された数の引数までは機能します(4で怠惰になりました)。ここから大きく食い物にされています(真剣に、クリックして賛成票を投じてください)。これは、事前に作成されたリストの前にある引数を文字どおり展開し、後ろの固定位置から正しい数を引き出すというトリックを使用します。次に、番号を追加して正しいマクロ名を呼び出します。クリア?いいえ!コードは次のとおりです。
#include <iostream>
// Pretty normal macro tricks
#define STRINGIZE(a) STRINGIZE1(a)
#define STRINGIZE1(a) STRINGIZE2(a)
#define STRINGIZE2(a) #a
#define CONCAT(a, b) CONCAT1(a, b)
#define CONCAT1(a, b) CONCAT2(a, b)
#define CONCAT2(a, b) a##b
// Faux-recursively dump all the arguments
#define DUMP_1(first) std::cout << STRINGIZE(first) << "='" << first << "'\n";
#define DUMP_2(first, ...) \
do {\
std::cout << STRINGIZE(first) << "='" << first << "': ";\
DUMP_1(__VA_ARGS__);\
} while (false)
#define DUMP_3(first, ...) \
do {\
std::cout << STRINGIZE(first) << "='" << first << "': ";\
DUMP_2(__VA_ARGS__);\
} while (false)
#define DUMP_4(first, ...) \
do {\
std::cout << STRINGIZE(first) << "='" << first << "': ";\
DUMP_3(__VA_ARGS__);\
} while (false)
// Count the arguments
// Construct the forward/backward list:
#define COUNT_ARGS(...) COUNT_ARGS_(__VA_ARGS__, RSEQ())
// Forward the list on (macro pain):
#define COUNT_ARGS_(...) COUNT_ARGS_N(__VA_ARGS__)
// The n+1th element is the count (predetermined to support up to n)
#define COUNT_ARGS_N(_1, _2, _3, _4, N, ...) N
#define RSEQ() 4, 3, 2, 1
// This just calls the correct DUMP_#
#define DUMP_(N, ...) CONCAT(DUMP_, N)(__VA_ARGS__)
// Start the line, and start the "recursion"
#define DUMP(...) \
do {\
std::cout << __PRETTY_FUNCTION__ << ':' << __LINE__ << ": "; \
DUMP_(COUNT_ARGS(__VA_ARGS__), __VA_ARGS__); \
} while (false)
int main(int argc, char* argv[])
{
DUMP(argc);
int i = 10;
const char str[] = "Hello, world";
DUMP(i, str);
return 0;
}
出力:
$ ./a.out
int main(int, char**):49: argc='1'
int main(int, char**):52: i='10': str='Hello, world'
編集:これはカウント部分(難しい部分)の単純なバージョンです:
#include <iostream>
#define COUNT_ARGS(...) COUNT_ARGS_(__VA_ARGS__, RSEQ())
#define COUNT_ARGS_(...) COUNT_ARGS_N(__VA_ARGS__)
#define COUNT_ARGS_N(_1, _2, _3, _4, _5, _6, N, ...) N
#define RSEQ() 6, 5, 4, 3, 2, 1
int main()
{
std::cout << COUNT_ARGS(a, b) << '\n';
std::cout << COUNT_ARGS(a, b, c, d) << '\n';
return 0;
}
出力:
1
2
これはどのように作動しますか?
私が持っているように、6までカウントするように設定したとしましょう。長いリストを構築し、7 番目の要素を取り出します。その値を取得するリストは、ユーザーが指定したすべての引数とその後に逆方向のカウントを配置することによって構築されるため、常に正しい値が含まれます。
したがって、別の引数を追加することで、後方カウントを 1 に沿ってプッシュし、そこからより高い数値を取得します。この絵を見てください: