3

タイトルは一目瞭然だと思いますが、私が達成しようとしていることを説明する例を次に示します。

#define PASTE2(_0, _1)  _0 ## _1

#define DEFINE_OPS_FOR_TYPE(TYPE)                   \
    int PASTE2(do_something_with_, TYPE)(void) {    \
        /* do_something_with_<TYPE> */              \
    }

charint、および単一単語の型ではすべて正常に機能しunsignedますが、複数のキーワードを持つ型やその他の型に関しては、トークンの貼り付け ( a ## b) を使用すると、空白 (例: ) が原因で有効な名前が生成されませんdo_something_with_foo bar

私が考えることができる最も簡単な解決策はDEFINE_OPS_FOR_TYPE、2 番目のパラメーターとして有効な名前を取るようにマクロを変更することです。例えば:

#define DEFINE_OPS_FOR_TYPE(TYPE, NAME_FOR_TYPE)            \
    int PASTE2(do_something_with_, NAME_FOR_TYPE)(void) {   \
        /* do_something_with_<NAME_FOR_TYPE> */             \
    }

これは期待どおりに機能しますが、非常に複雑であっても、他の可能な解決策に興味があります。を使用することを考え_Genericましたが、名前の定義にどのように役立つかわかりません。

別の解決策を考えられますか?

4

2 に答える 2

2

実行したいシンボルの宣言または定義のレベルではtypedef、問題の型の一意の識別子を取得する方法はほとんどありません。_Genericまたは同等の置換が開始されるのが遅すぎて、プリプロセッサに役立ちません。

しかし、このような問題を引き起こす標準型は限られています。したがって、これらを型定義するための規則を簡単に思い付くことができます。

そのような定義されたシンボルの使用面でどこ_Genericが役立つか。ここで、次のようなことができます

_Generic((X),
  unsigned long: do_something_with_ulong,
  unsigned char: do_something with_uchar,
  ...
)(X)

P99では、私はこのスキームに従います。すでに多くのサポート マクロが用意されています。

于 2013-01-03T12:30:24.437 に答える
1

引数が空のマクロを使用してしまいました。例:

#define STR2(x)             # x
#define STR(x)              STR2(x)
#define PASTE3(_1,_2,_3)    _1 ## _2 ## _3
#define FOO(_1,_2,_3)       PASTE3(_1, _2, _3)

printf("%s\n", STR(FOO(int,,)));
printf("%s\n", STR(FOO(unsigned, int,)));
printf("%s\n", STR(FOO(unsigned, long, long)));

ここでわかるように、出力は次のとおりです。

int
unsignedint
unsignedlonglong

空のマクロ引数の使用が標準に従って適切に定義されているかどうかは覚えていませんが、Clang 3.1 は-std=c11withに対して警告を発しないことはわかります-pedantic

試してみたい場合は、次のコードを使用してください。

#include <stdio.h>
#include <limits.h>

#define PASTE4(_1,_2,_3,_4) _1 ## _2 ## _3 ## _4

#define DEFINE_OPS_FOR_TYPE1(T1)        DEFINE_OPS_FOR_TYPE2(T1,)
#define DEFINE_OPS_FOR_TYPE2(T1, T2)    DEFINE_OPS_FOR_TYPE3(T1,T2,)
#define DEFINE_OPS_FOR_TYPE3(T1, T2, T3)                                    \
    int PASTE4(write_,T1,T2,T3)(FILE *file, void *data) {                   \
        T1 T2 T3 foo;                                                       \
        int written = fprintf(file, fmt_specifier(foo), *((T1 T2 T3 *)data));\
        return written > 0 ? 0 : -1;                                        \
    }

#define fmt_specifier(x)                \
    _Generic((x),                       \
        int: "%i",                      \
        unsigned int: "%u",             \
        unsigned long long: "%llu",     \
        default: NULL                   \
    )

DEFINE_OPS_FOR_TYPE1(int)
DEFINE_OPS_FOR_TYPE2(unsigned, int)
DEFINE_OPS_FOR_TYPE3(unsigned, long, long)

int main() {
    int var_int = INT_MAX;
    write_int(stdout, &var_int);
    printf("\n");
    unsigned int var_uint = UINT_MAX;
    write_unsignedint(stdout, &var_uint);
    printf("\n");
    unsigned long long var_ullong = ULLONG_MAX;
    write_unsignedlonglong(stdout, &var_ullong);
    printf("\n");
    return 0
}
于 2013-01-03T13:32:37.647 に答える