2

最初の作業コード:

#include <iostream>

// NOTE: requires compiler which has __PRETTY_FUNCTION__, like gcc or clang
#define DUMP(v) std::cerr << __PRETTY_FUNCTION__ << ':' << __LINE__ << ':' << #v << "='" << (v) << "'\n"

int main(int argc) {

    DUMP(argc);
    DUMP(argc+1);
    return 0;
}

stderr出力(gcc)を提供します:

int main(int):8:argc='1'
int main(int):9:argc+1='2'

ここで、任意の数の引数を持つ可変引数マクロを使用したいので、たとえば

DUMP(argc, argc+1);次のような出力で機能します。

int main(int):8:argc='1',argc+1='2'


しかし、私はまだ良い解決策を思いつくことができませんでした. これはマクロでも可能ですか?そうでない場合は、テンプレート、またはマクロとテンプレートの組み合わせはどうですか? C++11 と Boost は必要に応じて問題ありません。また、標準的な方法がない場合、ソリューションはgcc固有のものになる可能性があります。可変個引数 DUMP を上記のように機能させるか、少なくとも同等の情報を表示する実際のコードを探します。

4

2 に答える 2

1

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 に沿ってプッシュし、そこからより高い数値を取得します。この絵を見てください: ここに画像の説明を入力

于 2013-05-09T15:32:36.050 に答える