C ++マクロのオプションパラメータ


105

C ++マクロでオプションのパラメーターを取得する方法はありますか?ある種のオーバーロードもいいでしょう。


1
:Cに対して同じstackoverflow.com/questions/11761703/...は:プリプロセッサは基本的に同じであるので同じであるべきであるstackoverflow.com/questions/5085533/...
チロSantilli郝海东冠状病六四事件法轮功

たぶん、関数のオーバーロード、デフォルトのパラメーター、可変個のテンプレート、またはおそらく名前付きパラメーターのイディオムがあなたが探しているものです
smoothware

実際の解決策ではないと言って卑しい-upvoted 1と高upvotedものにあなたの選択した答えを更新してくださいNo you can't
アルバート・レンショウ

回答:


155

これを行う1つの方法を次に示します。引数のリストを2回使用します。最初にヘルパーマクロの名前を形成し、次にそのヘルパーマクロに引数を渡します。標準のトリックを使用して、マクロの引数の数を数えます。

enum
{
    plain = 0,
    bold = 1,
    italic = 2
};

void PrintString(const char* message, int size, int style)
{
}

#define PRINT_STRING_1_ARGS(message)              PrintString(message, 0, 0)
#define PRINT_STRING_2_ARGS(message, size)        PrintString(message, size, 0)
#define PRINT_STRING_3_ARGS(message, size, style) PrintString(message, size, style)

#define GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4
#define PRINT_STRING_MACRO_CHOOSER(...) \
    GET_4TH_ARG(__VA_ARGS__, PRINT_STRING_3_ARGS, \
                PRINT_STRING_2_ARGS, PRINT_STRING_1_ARGS, )

#define PRINT_STRING(...) PRINT_STRING_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)

int main(int argc, char * const argv[])
{
    PRINT_STRING("Hello, World!");
    PRINT_STRING("Hello, World!", 18);
    PRINT_STRING("Hello, World!", 18, bold);

    return 0;
}

これにより、マクロの呼び出し側は簡単になりますが、書き込み側は簡単ではありません。


1
これはかなりクールですが、PRINT_STRINGを実行しただけでは機能しないと思います。その場合、デフォルトのプリントアウトはありません(そして、それが実際に利用したいケースです)。それでも本当にクールな+1。
Cenoc

2
gccで動作します(非常に賢いです!):-) Visual Studioでは動作しません:-(
Tim Gradwell

3
@TimGradwell-MSVCコンパイラのバグが原因であることが確認されていますが、10年近く修正されていません。ただし、回避策があります
BeeOnRope 2017年

賢いですが、「GET_4th_ARG」で行っている「プッシュアウト」の問題のため、オプションの可変個引数マクロでは機能しません。
searchengine27

それPRINT_STRING_MACRO_CHOOSERも必要ですか?私はその内部本体に直接置き換えて、この全体をで呼び出すことができ(__VA_ARGS__)ますか?
Herrgott

85

Derek Ledbetterの回答に敬意を表し、古い質問を復活させたことをお詫びします。

それはやってpreceedする能力に別の場所で拾ったものを理解するの取得__VA_ARGS__##私は変化を考え出す許可を...

// The multiple macros that you would need anyway [as per: Crazy Eddie]
#define XXX_0()                     <code for no arguments> 
#define XXX_1(A)                    <code for one argument> 
#define XXX_2(A,B)                  <code for two arguments> 
#define XXX_3(A,B,C)                <code for three arguments> 
#define XXX_4(A,B,C,D)              <code for four arguments>  

// The interim macro that simply strips the excess and ends up with the required macro
#define XXX_X(x,A,B,C,D,FUNC, ...)  FUNC  

// The macro that the programmer uses 
#define XXX(...)                    XXX_X(,##__VA_ARGS__,\
                                          XXX_4(__VA_ARGS__),\
                                          XXX_3(__VA_ARGS__),\
                                          XXX_2(__VA_ARGS__),\
                                          XXX_1(__VA_ARGS__),\
                                          XXX_0(__VA_ARGS__)\
                                         ) 

私のように答えに出くわしたが、それがどのように機能するかがよくわからない場合は、次のコードから実際の処理を順に説明します...

XXX();
XXX(1); 
XXX(1,2); 
XXX(1,2,3); 
XXX(1,2,3,4); 
XXX(1,2,3,4,5);      // Not actually valid, but included to show the process 

なる...

XXX_X(, XXX_4(), XXX_3(),  XXX_2(),    XXX_1(),      XXX_0()         );
XXX_X(, 1,       XXX_4(1), XXX_3(1),   XXX_2(1),     XXX_1(1),       XXX_0(1)          );
XXX_X(, 1,       2,        XXX_4(1,2), XXX_3(1,2),   XXX_2(1,2),     XXX_1(1,2),       XXX_0(1,2)        );
XXX_X(, 1,       2,        3,          XXX_4(1,2,3), XXX_3(1,2,3),   XXX_2(1,2,3),     XXX_1(1,2,3),     XXX_0(1,2,3)      );
XXX_X(, 1,       2,        3,          4,            XXX_4(1,2,3,4), XXX_3(1,2,3,4),   XXX_2(1,2,3,4),   XXX_1(1,2,3,4),   XXX_0(1,2,3,4)    );
XXX_X(, 1,       2,        3,          4,            5,              XXX_4(1,2,3,4,5), XXX_3(1,2,3,4,5), XXX_2(1,2,3,4,5), XXX_1(1,2,3,4,5), XXX_0(1,2,3,4,5) );

これは6番目の引数にすぎません...

XXX_0(); 
XXX_1(1); 
XXX_2(1,2); 
XXX_3(1,2,3); 
XXX_4(1,2,3,4); 
5; 

PS:XXX_0の#defineを削除すると、コンパイルエラーが発生します[引数なしのオプションが許可されていない場合]。

PPS:無効な状況(例:5)が、プログラマーに明確なコンパイルエラーを与えるものであるとよいでしょう。

PPPS:私は専門家ではないので、コメント(良い、悪い、その他)を聞いてとても幸せです!


3
MACRO名であるはずの選択された引数を#(ポンド記号)を使用して文字列に変換し、その最初のn文字を予想されるプレフィックスと比較し、一致しない場合は、有益な情報を出力すると、明確なコンパイルエラーが発生する可能性があります。エラー。
AturSams 2014年

1
うわー、これが機能するかどうかはわかりませんが、少なくとも非常にクリエイティブです!
限定的な贖罪

4
なぜ最初の引数は常に空ですか?なぜ省略できないのですか:XXX_X(,##__VA_ARGS__,` ... XXX_X(、XXX_4()、XXX_3()、XXX_2()、XXX_1()、XXX_0()); `
rahman

2
空の最初の引数(コンマ)は重要です。## __ VA_ARGS__(コンマが前にある場合)– ## __ VA_ARGS__が何も展開されない場合は、コンマを削除します。"Becomes ..."の例では、最初の(引数なし)行に6つのパラメーターしかないのでそれを確認できますが、残りは7になります。このトリックにより、引数なしの状況が機能します
David Sorkovsky

@Eric-Microsoftコンパイラのバグが原因ですが、回避策としてこの質問見ることができます
BeeOnRope

31

C ++マクロはCから変更されていません。Cには関数のオーバーロードとデフォルトの引数がなかったため、マクロ用の引数はありませんでした。だからあなたの質問に答えるために:いいえ、それらの機能はマクロには存在しません。唯一のオプションは、異なる名前で複数のマクロを定義することです(またはマクロをまったく使用しません)。

補足として:C ++では、マクロからできるだけ離れることが一般的には良い習慣と考えられています。このような機能が必要な場合は、マクロを使いすぎている可能性があります。


4
マクロを「オーバーロード」することが不可能である理由は、マクロに固有の型がないためです。マクロは単純に展開されます。
mk12

2
私はできるだけのマクロを使用していますが、私は、トレース出力を介してデバッグするようなものでかなり容易になることがわかる__FILE____LINE__、そのような...
クリスチャン・セヴェリン

良い答えではありません。これは良い答えです:stackoverflow.com/q/27049491/893406
v.oddou

条件付きコンパイルとデバッグ/ロギングは、マクロが本当に便利で正当なドメインです。すべての真面目なプログラマーはそれを知っています。マクロを使用して定数を定義したり、クレイジーなCレベルのコーディングを行ってコンテナテンプレートを作成したりすることはお勧めしません。C ++がさらに多くの機能をマクロに追加することを望みます。それらはテンプレートに直交しています。もちろん、ドメイン固有言語(アスペクト)のコンパイラーにジェネレーターを追加できるコードレットがベストです。
Lothar

1
また、マクロはC ++言語オプション以外の完全なものであるため、これは良い答えではないと思います。これは、コンパイラーの前に処理されるためです。したがって、他のことを行うことができ、コンパイラやリンカーがコードを最適化する必要はありません。おそらく最適化しないためです。
alabamajack 2016

26

最大に関してはデレック・レッドベターデビッドSorkovskySyphorlate一緒にして、空のマクロの引数を検出するための独創的な方法とその回答について、イェンスGustedt

https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/

最後に私はすべてのトリックを組み込んだものを思いついたので、解決策は

  1. 標準のC99マクロのみを使用して、関数のオーバーロードを実現します。GCC/ CLANG / MSVC拡張は含まれません(つまり、, ##__VA_ARGS__GCC / CLANGの特定の式によるコンマの飲み込み、および##__VA_ARGS__MSVCの暗黙的な飲み込み)。したがって--std=c99、必要に応じて、不足しているものをコンパイラに渡してもかまいません=)
  2. 以下のための作品ゼロ引数と同様に、引数の数に制限はありません、あなたはあなたのニーズに合わせて、さらにそれを拡張した場合
  3. 合理的にクロスプラットフォームで動作し、少なくともテスト済み

    • GNU / Linux + GCC(CentOS 7.0 x86_64上のGCC 4.9.2)
    • GNU / Linux + CLANG / LLVM、(CentOS 7.0 x86_64上のCLANG / LLVM 3.5.0)
    • OS X + Xcode(OS X Yosemite 10.10.1上のXCode 6.1.1)
    • Windows + Visual Studio(Windows 7 SP1 64ビット上のVisual Studio 2013 Update 4)

レイジーの場合は、この投稿の最後までスキップしてソースをコピーしてください。以下は詳細な説明です。これは、__VA_ARGS__私のような一般的な解決策を探しているすべての人々を助け、刺激することを願っています。=)

ここにその様子を示します。第1のユーザ可視オーバーロード「機能」を定義する、私はそれを名前create、および関連する実際の関数定義realCreate、及び引数の数が異なるマクロ定義CREATE_2CREATE_1CREATE_0以下に示すように、。

#define create(...) MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)

void realCreate(int x, int y)
{
  printf("(%d, %d)\n", x, y);
}

#define CREATE_2(x, y) realCreate(x, y)
#define CREATE_1(x) CREATE_2(x, 0)
#define CREATE_0() CREATE_1(0)

このMACRO_CHOOSER(__VA_ARGS__)部分は最終的にマクロ定義名に解決され、2番目の(__VA_ARGS__)部分はパラメーターリストで構成されます。したがって、ユーザーがにcreate(10)解決するための呼び出しCREATE_1(10)で、CREATE_1一部はからMACRO_CHOOSER(__VA_ARGS__)(10)一部は2番目から発生し(__VA_ARGS__)ます。

MACRO_CHOOSER場合は、そのトリック使って__VA_ARGS__空になって、次の式は、プリプロセッサによって、有効なマクロ呼び出しに連結されました:

NO_ARG_EXPANDER __VA_ARGS__ ()  // simply shrinks to NO_ARG_EXPANDER()

独創的に、この結果のマクロ呼び出しを次のように定義できます。

#define NO_ARG_EXPANDER() ,,CREATE_0

2つのコンマに注意してください。それらはすぐに説明されます。次に役立つマクロは

#define MACRO_CHOOSER(...) CHOOSE_FROM_ARG_COUNT(NO_ARG_EXPANDER __VA_ARGS__ ())

だからの呼び出し

create();
create(10);
create(20, 20);

実際に拡張されます

CHOOSE_FROM_ARG_COUNT(,,CREATE_0)();
CHOOSE_FROM_ARG_COUNT(NO_ARG_EXPANDER 10 ())(10);
CHOOSE_FROM_ARG_COUNT(NO_ARG_EXPANDER 20, 20 ())(20, 20);

マクロ名が示すように、後で引数の数を数えます。ここで別のトリックがあります。プリプロセッサは単純なテキスト置換のみを行います。かっこ内にあるコンマの数から、マクロ呼び出しの引数の数を推測します。コンマで区切られた実際の「引数」は、有効な構文である必要はありません。任意のテキストにすることができます。つまり、上記の例でNO_ARG_EXPANDER 10 ()は、中間呼び出しの1つの引数としてカウントされます。NO_ARG_EXPANDER 2020 ()下部呼び出しの2つの引数としてそれぞれカウントされます。

次のヘルパーマクロを使用してさらに拡張する場合

##define CHOOSE_FROM_ARG_COUNT(...) \
  FUNC_RECOMPOSER((__VA_ARGS__, CREATE_2, CREATE_1, ))
#define FUNC_RECOMPOSER(argsWithParentheses) \
  FUNC_CHOOSER argsWithParentheses

末尾,の後は、CREATE_1と言って(偽陽性)の誤差を抑え、GCC / CLANGための回避策でISO C99 requires rest arguments to be used渡すときに-pedantic、あなたのコンパイラに。これFUNC_RECOMPOSERはMSVCの回避策です。または、マクロ呼び出しの括弧内の引数(つまり、コンマ)の数を正しくカウントできません。結果はさらに解決されます

FUNC_CHOOSER (,,CREATE_0, CREATE_2, CREATE_1, )();
FUNC_CHOOSER (NO_ARG_EXPANDER 10 (), CREATE_2, CREATE_1, )(10);
FUNC_CHOOSER (NO_ARG_EXPANDER 20, 20 (), CREATE_2, CREATE_1, )(20, 20);

あなたが目にしたかもしれないように、私たちが必要とする最後の唯一のステップは、必要なマクロバージョン名を最終的に選択するために標準の引数カウントトリックを採用することです:

#define FUNC_CHOOSER(_f1, _f2, _f3, ...) _f3

結果を解決する

CREATE_0();
CREATE_1(10);
CREATE_2(20, 20);

そして確かに私たちに望ましい実際の関数呼び出しを与えます:

realCreate(0, 0);
realCreate(10, 10);
realCreate(20, 20);

すべてをまとめると、読みやすくするためにステートメントを並べ替えて、2引数の例のソース全体を次に示します。

#include <stdio.h>

void realCreate(int x, int y)
{
  printf("(%d, %d)\n", x, y);
}

#define CREATE_2(x, y) realCreate(x, y)
#define CREATE_1(x) CREATE_2(x, 0)
#define CREATE_0() CREATE_1(0)

#define FUNC_CHOOSER(_f1, _f2, _f3, ...) _f3
#define FUNC_RECOMPOSER(argsWithParentheses) FUNC_CHOOSER argsWithParentheses
#define CHOOSE_FROM_ARG_COUNT(...) FUNC_RECOMPOSER((__VA_ARGS__, CREATE_2, CREATE_1, ))
#define NO_ARG_EXPANDER() ,,CREATE_0
#define MACRO_CHOOSER(...) CHOOSE_FROM_ARG_COUNT(NO_ARG_EXPANDER __VA_ARGS__ ())
#define create(...) MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)

int main()
{
  create();
  create(10);
  create(20, 20);
  //create(30, 30, 30);  // Compilation error
  return 0;
}

複雑で醜い、API開発者に負担がかかりますが、C / C ++関数のオプションのパラメーターをオーバーロードして設定するためのソリューションがクレイジーな人々に提供されます。予定されているオーバーロードされたAPIの使用は、非常に楽しく快適になっています。=)

このアプローチをさらに単純化できる可能性がある場合は、次のURLでお知らせください。

https://github.com/jason-deng/C99FunctionOverload

刺激を与えて、この作品を達成するために導いてくれた素晴らしい人々のすべてに再び特別に感謝します!=)


3
これを3つまたは4つの機能に拡張するにはどうすればよいですか?
Phylliida、2015

@Phylliida ideone.com/jD0Hm5-0〜5 個の引数がサポートされています。
xx

9

Visual C ++で動作するVA_NARGSソリューションを苦労して検索する人のために。次のマクロは、Visual C ++ Express 2010で問題なく(また、パラメーターが0でも!)機能しました。

#define VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,N,...) N
#define VA_NUM_ARGS_IMPL_(tuple) VA_NUM_ARGS_IMPL tuple
#define VA_NARGS(...)  bool(#__VA_ARGS__) ? (VA_NUM_ARGS_IMPL_((__VA_ARGS__, 24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1))) : 0

オプションのパラメーターを含むマクロが必要な場合は、次のようにできます。

//macro selection(vc++)
#define SELMACRO_IMPL(_1,_2,_3, N,...) N
#define SELMACRO_IMPL_(tuple) SELMACRO_IMPL tuple
#define mymacro1(var1) var1
#define mymacro2(var1,var2) var2*var1
#define mymacro3(var1,var2,var3) var1*var2*var3
#define mymacro(...) SELMACRO_IMPL_((__VA_ARGS__, mymacro3(__VA_ARGS__), mymacro2(__VA_ARGS__), mymacro1(__VA_ARGS__))) 

それは私にとってもVCでうまくいきました。ただし、パラメータがゼロの場合は機能しません。

int x=99;
x=mymacro(2);//2
x=mymacro(2,2);//4
x=mymacro(2,2,2);//8

取得中unresolved external symbol _bool referenced in function _main
Avidan Borisov 2013年

はい、それはいくつかのケースで発生する可能性があります。bool(#__ VA_ARGS__)?実行時に評価されるため、他のマクロとは異なります。場合によっては、コードのその部分を省略できます。
Syphorlate

2
私は実際には完全に機能するpastebin.com/H3T75dcnで終わっています(引数も0)。
Avidan Borisov 2013年

リンクをありがとう、そうです、あなたはsizeofを使用してもそれを行うことができますが、私にとってはそれはいくつかのケースでは機能しませんでしたが、原理は同じです(ブール評価)。
Syphorlate

失敗する例をいくつか挙げていただけますか?
Avidan Borisov 2013年


5
#include <stdio.h>

#define PP_NARG(...) \
    PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
#define PP_NARG_(...) \
    PP_ARG_N(__VA_ARGS__)
#define PP_ARG_N( \
    _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ 
    _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
    _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
    _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
    _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
    _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
    _61,_62,_63,N,...) N
#define PP_RSEQ_N() \
    63,62,61,60,                   \
    59,58,57,56,55,54,53,52,51,50, \
    49,48,47,46,45,44,43,42,41,40, \
    39,38,37,36,35,34,33,32,31,30, \
    29,28,27,26,25,24,23,22,21,20, \
    19,18,17,16,15,14,13,12,11,10, \
    9,8,7,6,5,4,3,2,1,0

#define PP_CONCAT(a,b) PP_CONCAT_(a,b)
#define PP_CONCAT_(a,b) a ## b

#define THINK(...) PP_CONCAT(THINK_, PP_NARG(__VA_ARGS__))(__VA_ARGS__)
#define THINK_0() THINK_1("sector zz9 plural z alpha")
#define THINK_1(location) THINK_2(location, 42)
#define THINK_2(location,answer) THINK_3(location, answer, "deep thought")
#define THINK_3(location,answer,computer) \
  printf ("The answer is %d. This was calculated by %s, and a computer to figure out what this"
          " actually means will be build in %s\n", (answer), (computer), (location))

int
main (int argc, char *argv[])
{
  THINK (); /* On compilers other than GCC you have to call with least one non-default argument */
}

免責事項:ほとんど無害。


コードにエラーがあります。行ってください:%s/MY_MACRO_/THINK_/g:)
ジョアン・ポルテラ

また、それはグラムを使用して引数なしの仕事++なかったi686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5664)
ジョアン・ポルテラ

1
空のトークンは有効なプレースホルダーであるため、variadiacマクロには引数はありません。
ポールフルツII 2013

3

それは、プリプロセッサが実際に設計されたものではありません。

とはいえ、可読性が少し高い、非常に困難なマクロプログラミングの領域に参入したい場合は、Boostプリプロセッサライブラリをご覧ください。結局のところ、3つの完全にチューリング互換のプログラミングレベル(プリプロセッサ、テンプレートメタプログラミング、および基本レベルのC ++)がなければ、C ++にはなりません!


3
#define MY_MACRO_3(X,Y,Z) ...
#define MY_MACRO_2(X,Y) MY_MACRO(X,Y,5)
#define MY_MACRO_1(X) MY_MACRO(X,42,5)

呼び出しの時点で、渡す引数の数がわかっているので、オーバーロードする必要はありません。


2
実際にその機能の存在について質問していました。
Cenoc

3

Derek Ledbetterのコードのより簡潔なバージョン:

enum
{
    plain = 0,
    bold = 1,
    italic = 2
};


void PrintString(const char* message = NULL, int size = 0, int style = 0)
{
}


#define PRINT_STRING(...) PrintString(__VA_ARGS__)


int main(int argc, char * const argv[])
{ 
    PRINT_STRING("Hello, World!");
    PRINT_STRING("Hello, World!", 18);
    PRINT_STRING("Hello, World!", 18, bold);

    return 0;
}

3

恐ろしいマクロモンスターの大ファンとして、私はJason Dengの答えを拡張して実際に使用できるようにしたかったのです。(良くも悪くも。)新しいマクロを作成するたびに大きなアルファベットのスープを変更する必要があり、異なる量の引数が必要な場合はさらに悪いため、オリジナルはあまり使いやすくありません。

だから私はこれらの機能を備えたバージョンを作りました:

  • 0引数のケースは機能します
  • 乱雑な部分に変更を加えない1〜16個の引数
  • マクロ関数の記述が簡単
  • gcc 10、clang 9、Visual Studio 2017でテスト済み

現在、最大16個の引数を作成しましたが、さらに必要な場合(実際には?ばかげているだけです...)、FUNC_CHOOSERとCHOOSE_FROM_ARG_COUNTを編集して、NO_ARG_EXPANDERにいくつかのコンマを追加できます。

実装の詳細については、Jason Dengの優れた回答を参照してください。ただし、ここにコードを記述します。

#include <stdio.h>

void realCreate(int x, int y)
{
    printf("(%d, %d)\n", x, y);
}

// This part you put in some library header:
#define FUNC_CHOOSER(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, ...) _f16
#define FUNC_RECOMPOSER(argsWithParentheses) FUNC_CHOOSER argsWithParentheses
#define CHOOSE_FROM_ARG_COUNT(F, ...) FUNC_RECOMPOSER((__VA_ARGS__, \
            F##_16, F##_15, F##_14, F##_13, F##_12, F##_11, F##_10, F##_9, F##_8,\
            F##_7, F##_6, F##_5, F##_4, F##_3, F##_2, F##_1, ))
#define NO_ARG_EXPANDER(FUNC) ,,,,,,,,,,,,,,,,FUNC ## _0
#define MACRO_CHOOSER(FUNC, ...) CHOOSE_FROM_ARG_COUNT(FUNC, NO_ARG_EXPANDER __VA_ARGS__ (FUNC))
#define MULTI_MACRO(FUNC, ...) MACRO_CHOOSER(FUNC, __VA_ARGS__)(__VA_ARGS__)

// When you need to make a macro with default arguments, use this:
#define create(...) MULTI_MACRO(CREATE, __VA_ARGS__)
#define CREATE_0() CREATE_1(0)
#define CREATE_1(x) CREATE_2(x, 0)
#define CREATE_2(x, y) \
    do { \
        /* put whatever code you want in the last macro */ \
        realCreate(x, y); \
    } while(0)


int main()
{
    create();
    create(10);
    create(20, 20);
    //create(30, 30, 30);  // Compilation error
    return 0;
}

2

図書館BOOST_PP_OVERLOADから利用できますboost

公式のブーストドキュメントの例:

#include <boost/preprocessor/facilities/overload.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/preprocessor/arithmetic/add.hpp>

#define MACRO_1(number) MACRO_2(number,10)
#define MACRO_2(number1,number2) BOOST_PP_ADD(number1,number2)

#if !BOOST_PP_VARIADICS_MSVC

#define MACRO_ADD_NUMBERS(...) BOOST_PP_OVERLOAD(MACRO_,__VA_ARGS__)(__VA_ARGS__)

#else

// or for Visual C++

#define MACRO_ADD_NUMBERS(...) \
  BOOST_PP_CAT(BOOST_PP_OVERLOAD(MACRO_,__VA_ARGS__)(__VA_ARGS__),BOOST_PP_EMPTY())

#endif

MACRO_ADD_NUMBERS(5) // output is 15
MACRO_ADD_NUMBERS(3,6) // output is 9

0

必要に応じて、マクロを使用してvar argsで実行できます。現在、オプションのパラメーターやマクロのオーバーロードなどはありません。


-1

マクロで引数をカウントする(デレック・レッドベター、デビッドSorkovsky、そしてジョー・Dから)上記の例はいずれもマイクロソフトVCC 10を使用して私のために働いていない__VA_ARGS__引数は常に(トークンizingそれが持つ単一の引数として考えられている##ので、そうでありませんか)これらの例が依存する引数シフトは機能しません。

したがって、上記の他の多くの人が述べたように、短い答え:いいえ、マクロをオーバーロードしたり、マクロにオプションの引数を使用したりすることはできません。


1
できますが、C99またはC ++ 11でのみ可能です(__VA_ARGS__があるため)。VC2010はC89 / C ++ 03です(C ++ 11のいくつかのビットが増え始めていますが、まだそうではありません)。
puetzk
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.