私は奇妙な状況で、いくつかのCコードに構文上の優しさを追加しようとしています。私は単なる構造体である数字の三つ組を持っています。_引数の最小数を超えた一般的なパラメータ
typedef struct {int x, y, z} coord;
ここでは、引数として2つの構造体をとる関数がいくつかあります。私は自分自身はかなり定期的に、私は
coord foo;
/* initialize foo with something */
int n = boxes_inside((coord){.x = 0, .y = 0, .z = 0}, foo);
ネヴァーマインド、これを非常に醜いであることがわかり固定引数でそれを呼び出す見つける
static inline int boxes_inside(const coord min, const coord max)
{
return (1 + max.x - min.x) * (1 + max.y - min.y) * (1 + max.z - min.z);
}
:最も簡単な1は、3D空間内の座標の数が2つの構造体を定義してカウント例がばかげていると、より複雑な機能にはより意味をなさない。
私は_Generic
を使用して、トリプレットのintまたはstructを渡すと考えました。
int boxes_inside_cc(const coord min, const coord max);
int boxes_inside_ci(const coord min, const int maxx, const int maxy, const int maxz);
int boxes_inside_ic(const int minx, const int miny, const int minz, const coord max);
int boxes_inside_ii(const int minx, const int miny, const int minz, const int maxx, const int maxy, const int maxz);
#define arg1(a, ...) (a)
#define arg2(a, b ...) (b)
#define arg4(a, b, c, d, ...) (d)
#define boxes_inside(...) _Generic(arg1(__VA_ARGS__), \
coord: _Generic(arg2(__VA_ARGS__), coord: boxes_inside_cc, int: boxes_inside_ci) \
int: _Generic(arg4(__VA_ARGS__), coord: boxes_inside_ic, int: boxes_inside_ii) \
)(__VA_ARGS__)
「選択されていない選択肢の表現は決して評価されないので、これはうまくいくと思いました。 (ref)ですが、これはdone after preprocessingであるため、選択されていない選択項目でもすべてのマクロが展開されます。特に
私は今、次の呼び出しを行う場合、:
coord min, max;
/* stuff */
int n = boxes_inside(min, max);
を私はarg4(__VA_ARGS__)
試行が_Genericのこのブランチは後に評価されることはありませんにもかかわらず、それが実際に持っているよりも多くのパラメータを拡大するという問題を取得しますに。
#define boxes_inside_(a, b, c, d, ...) _Generic((a), \
coord: boxes_inside_ii(a, b, c, d.x, d.y, d.z), \
int: boxes_inside_ii(a, b, c, d, __VA_ARGS__) \
)
#define boxes_inside(a, ...) _Generic((a), \
coord: boxes_inside_(a.x, a.y, a.z, __VA_ARGS__) \
int: boxes_inside_(a, __VA_ARGS__) \
)
しかし、これは当然同じ理由で失敗します:
は、だから私は、その後、常に十分な引数を持つように構造体を拡張しようとしたがboxes_inside(min, max)
特定はまだ上
boxes_inside_(min max)
に展開して、両方の枝は、他のマクロを展開しますすでに知っている支店は使用されません。
これには方法がありますか?または、使用するパラメータの最小数を超えてパラメータをテストする場合は、_Generic
の式は基本的に役に立たないのですか?
[Boost.PP](http://www.boost.org/doc/libs/master/libs/preprocessor/doc/ref/overload.html)の魔法をこの周りに置くことをお勧めします。あなたはコーヒーマシンですので、あなたはおそらくあなたが何をしているのか知っています。 – Quentin
@Quentin私は本当に[引数の数にマクロをオーバーロードする]ことから始めることができます(https://stackoverflow.com/questions/11761703/overloading-macro-on-number-of-arguments)。その後、型を分割するだけです_Genericは、おそらくブーストプリプロセッサライブラリがとにかく近いものです。しかし、それは私が最初にそれを使用して_Genericの制限でうんざりされ、私は何か愚かなものを見逃していないのだろうかと思っている以上です... – Cimbali
私はこのアプローチが動作しないと思う;ジェネリックのすべてのブランチは、選択されていなくても制約違反がない必要があります。 –