1

まさに、プログラミング言語にマクロは必要ありません。たとえば、Java はマクロがなくても問題なく動作します。通常、マクロはコードをより明確かつ短くすると同時に、より危険なものにします。

では、マクロを使用する最良の方法は何ですか? コードで話しましょう。

4

5 に答える 5

5

マクロを使用すると、次のような問題に対する美しいソリューションを作成できます。

  • 値を文字列表現に、またはその逆に変換できるように列挙型を定義します。

periodメンバーがonefivetenfifteenおよび と呼ばれる列挙型を定義するとしますthirty。次に、これを行う方法は次のとおりです。

  • まず、次のようなヘッダー ファイルを作成しますperiod_items.h

    //period_items.h
    
    //Here goes the items of the enum
    //it is not a definition in itself!
    E(one)
    E(five)
    E(ten)
    E(fifteen)
    E(thirty)
    
  • 次に、次のような別のヘッダー ファイルを作成しますperiod.h

    //period.h
    #include <string>
    
    //HERE goes the enum definition!
    enum period 
    {
       #define E(item)  item,
         #include "period_items.h" //it dumps the enum items in here!
       #undef E
       period_end
    };
    
    period to_period(std::string const & name)
    {
       #define E(item)  if(name == #item) return item;
         #include "period_items.h"
       #undef E
       return period_end;
    }
    

これで、関数を単純に含めperiod.hて使用できるようになりました。to_period:-)

この関数を次のように追加することもできますperiod.h

std::string to_string(period value)
{
    #define E(item)  if(value == item) return #item;
        #include "period_items.h"
    #undef E
    return "<error>";
}

今、あなたはこれを書くことができます:

#include "period.h"

period v = to_period("fifteen"); //string to period
std::string s = to_string(v);  //period to string

このソリューションが美しい理由

列挙型にさらにいくつかのメンバーを追加したい場合は、次のように追加するだけですperiod_items.h

    //period_items.h

    //Here goes the items of the enum
    //it is not a definition in itself!
    E(one)
    E(five)
    E(ten)
    E(fifteen)
    E(thirty)
    E(fifty)       //added item!
    E(hundred)     //added item!
    E(thousand)    //added item!

これで完了です。to_string何も変更しなくても問題なく動作しto_periodます。

--

私はこの解決策を自分の解決策から別の問題に取り、ここに投稿しました:

于 2012-07-27T10:22:34.097 に答える
3

私は最良の方法は使用することだと思いますinline

マクロのすべての利点とコンパイル時のすべてのチェックを利用できます

C++ でマクロが役立つ主な目的は、コンパイルを制御することです。何かのようなもの:

#ifdef DEBUG:
    //print some debug information
#endif

また

#ifdef OS_WINDOWS
    //windows specific code
#
于 2012-07-27T10:10:57.817 に答える
1

私は他に何も機能しない場所でのみマクロを使用します。

1つの例は、たとえば、エラー値から文字列への簡単なマッピングです。

switch(code) {
    case ERR_OK: return "ERR_OK";
    case ERR_FOO: return "ERR_FOO";
    :

私は次のような単純なマクロを使用します

#define CASE_STR(x) case x: return #x

だから私はこれを単純化することができます

switch(code) {
    CASE_STR(ERR_OK);
    CASE_STR(ERR_FOO);
    :

ただし、これらのケースは通常、デバッグ用です。

また、ブーストプリプロセッサスイートを使用して一度展開するGLSL(OpenGL Shading Language)ループを作成しました。これは、次のように使用できます。

const char *shader = "#version 120\n"
"..."
GLSL_UNROLL_FOR("int i",0,10,\
    "foo += i\n" \
)
"...";
于 2012-07-27T10:32:07.010 に答える
1

次に例を示します(簡単に保守できます)。

enum id {
#define ITEM(id, s) id,
# include "foo.itm"
#undef ITEM
    nbItem
};

static char const *const s[] = {
#define ITEM(id, s) s,
# include "foo.itm
#undef ITEM
}
于 2012-07-27T10:32:50.763 に答える
1

私の非常に個人的な意見では、優れたマクロは非常にまれなものです。それらのほとんどは時限爆弾のようなものなので、私はそれらをできるだけ避けようとしています.

マクロが適切であるためには、次のことを行う必要があります。

  • シンプルに。
  • あいまいになることはありません
  • コード構造にブレーキをかけないでください (私は のようなマクロを見たことがありますが#define MACRO } someCode {、これは最悪です)。
  • 例外をスローできない、またはそのようなものは、基本的に、デバッグを難しくしてはなりません
  • 意味が分かりやすい名前にする
  • たとえば、コンパイル制御やヘッダー ガードなどのインライン関数の代わりにマクロを使用するには、十分な理由あるはずです。
于 2012-07-27T10:15:16.520 に答える