9

私は C でオブジェクト指向を行おうとしていますが、表記法に構文糖マクロが必要です

object->vtable->method(object, arg1, arg2)

の中へ

send(object, method, arg1, arg2)

残念ながら、メソッドが引数を取らない場合、末尾のコンマの問題が発生します

send(object, method)

与える

object->vtable->method(object, )

これを行う移植可能な(いいえ##__VA_ARGS__または Visual Studio) 方法はありますか?

1つ見つけましたが、オブジェクトとメソッドを交換する必要があります

#define FIRST_ARG_(N, ...) N
#define FIRST_ARG(args) FIRST_ARG_(args)
#define send(msg, ...) \
 FIRST_ARG(__VA_ARGS__)->vtable->msg(__VA_ARGS__)

許可する

send(method, object)
send(method, object, arg1, arg2)

編集

以下からの2つの良い答えの助けを借りて、これらのマクロでそれを行います. 最大 16 個の引数で動作しますが、簡単に拡張できます

#define SEND_NO_ARG(obj, msg) obj->vtable->msg(obj)
#define SEND_ARG(obj, msg, ...) obj->vtable->msg(obj, __VA_ARGS__)

#define GET_18TH_ARG(arg1, arg2, arg3, arg4, arg5, \
    arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, \
    arg16, arg17, arg18, ...) arg18
#define SEND_MACRO_CHOOSER(...) \
    GET_18TH_ARG(__VA_ARGS__, \
            SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \
            SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \
            SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, SEND_ARG, \
            SEND_NO_ARG, )

#define SEND(...) SEND_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)
4

2 に答える 2

4

短い答え、はい、ポータブルな方法で可能です。

長い答え: これは複雑で、おそらく自分で実装したくないでしょう。マクロが受け取る引数をカウントし、その数に従ってアクションを実行する方法があります。P99は、これを実現するのに役立つ一連のマクロを実装しています。2 つの基本マクロsend_2を実装する場合、2 つのケースでは次のようsend_moreに実装できます。send

#define send(...)                     \
 P99_IF_LT(P99_NARG(__VA_ARGS__), 3)  \
 (send_2(__VA_ARGS__))                \
 (send_more(__VA_ARGS__))

技術的には、P99 のこれらの構造には、150 (またはそれ以上) を超える引数を処理できないという制限がありますsend

sendところで、おそらく、マクロを呼び出すことは実際には良い考えではないことをご存知でしょう。通常、マクロはすべて大文字にする方が好まれます。また、ほとんどの場合、ライブラリ/パッケージに固有の名前プレフィックスを付けることをお勧めします ( AC245_SEND.

于 2013-12-28T20:53:58.923 に答える
1

この回答では、パラメータの数を数え、最初の 2 つの引数としてobjectandを使用できるようにするテクニックが説明されています。method

于 2013-12-28T20:16:00.763 に答える