2

私は、C++ の列挙型を簡単にするための小さなライブラリを作成しています。構文は次のようなものです。

ENUM_START(MyEnum)
    ENUM_VAL(Val1)
    ENUM_VAL(Val2)
    ...
ENUM_END

このマクロは、たとえば次のアクセスを許可するクラス MyEnum を作成します。

MyEnum bla=MyEnum::Val1;
for(MyEnum::iterator iter=MyEnum::begin();iter!=MyEnum::end();++iter)
    cout << iter->toString();

追加のデータ (文字列など) を列挙値に格納するなど、さらにいくつかの機能があります。

マクロは完成して機能しますが、上記のように定義するのは簡単ではありません。このためには、後で呼び出すことができる ENUM_VAL マクロを使用して初期化関数のリストを作成する方法が必要です。次の boost::mpl アプローチのようなもの:

typedef mpl::vector<> list__COUNTER__;
#define ENUM_VAL(Name)                                                         \
    ...                                                                        \
    struct Init##Name{void init() {initialization code}};                      \
    typedef mpl::push_back<                                                    \
        list##(__COUNTER-1),                                                   \
        Init##Name                                                             \
      >::type list##__COUNTER__;                                               \

このように list##(__COUNTER__-1) は最後に Init##Name 型を含み、最後に mpl foreach を使用してすべての格納された型で init() を呼び出すことができます。

今の問題はネーミングです。マクロのインスタンス化ごとに __COUNTER__ を 2 回使用する必要があり、これによりカウンターが 2 回インクリメントされます。さっき検索して知った

  • C プリプロセッサは、変数に名前を付けるときに (__COUNTER__-1) を計算しません
  • インクリメントせずに __COUNTER__ を読み取る方法はありません。

そのため、後で呼び出すことができる関数のリストを収集する別の方法が必要です。

4

2 に答える 2

2

Boost.Preprocessorを使用できます。具体的には、sequenceです。これにより、次のようなマクロの使用法が得られます。

MAKE_ENUM(MyEnum, (Val1)(Val2)(Val3))

などを使用するSEQ_ENUMと、SEQ_FOR_EACH_I比較的簡単にコードを生成できます。

また、提案されたBoost.Enumもありましたが、これはすでにニーズに合っている可能性があります。

于 2012-01-19T19:40:13.920 に答える
1

テンプレートメタプログラミングとは別に、プリプロセッサがコードを見る前にスクリプトとして実行できるテンプレートエンジンがあります。 これには、単なるコードであるという追加の利点があるため、デバッグが容易になります。

欠点は、誰かが何かを変更したい場合に別のツール要件を追加することです。

私は以前にこれにチーターを使用しましたが、結果に失望することはありませんでした。

于 2012-01-19T19:46:59.980 に答える