6

次のようなものを使用して、アプリケーションのポリシーを作成しました。

ポリシー クラスは次のようになります。

struct Policy {
  static void init();
  static void cleanup();
  //...
};

template <class CarT, class CdrT>
struct Cons {
  static void init() {
    CarT::init();
    CdrT::init();
  }
  static void cleanup() {
    CdrT::cleanup();
    CarT::cleanup();
  }
  //...
};

ポリシーを作成するには:

typedef Cons<Policy1, Cons<Policy2, Cons<Policy3, Policy4> > > MyPolicy;

MyPolicy を使用するには:

init_with<MyPolicy>(...);
//...
cleanup_with<MyPolicy>(...);

彼らが呼び出す場所:

MyPolicy::init_options(); // calls Policy1 to 4's init in order

MyPolicy::cleanup(); // calls Policy1 to 4's cleanup in reverse order

基本的に、Cons はここで型リストを作成します。それはかなり簡単です。ただし、typedef の cons 行はちょっと見づらいです。これを行うことができるポリシー コンバイナーがあると理想的です。

typedef CombinePolicy<Policy1, Policy2, Policy3, Policy4> MyPolicy;

任意の数のポリシーを設定できるため、CombinePolicy には C++0x での可変個引数テンプレートのサポートが必要です。これは最先端のコンパイラで実験的にのみ利用可能です。ただし、boost:mpl ライブラリは、一連の前処理のトリックを使用して問題を解決/回避したようです。私は次のようなものを使用できると思います:

typedef mpl::list<Policy, Policy2, Policy3, Policy4> Policies;

そして、次を呼び出します。

init_with<Policies>(...);

次に使用します:

typedef iter_fold<Policies, begin<Policies>::type,
                  some_magic_lambda_expression>::type MyPolicy;

明らかに、ここでsome_magic_lambda_expressionを理解するのに少し苦労しています。ここでは、mpl の専門家にとっては非常に些細なことだと思います。

前もって感謝します。

4

3 に答える 3

9

質問に満足のいく回答が得られなかったので、boost::mpl のソースを掘り下げることに時間を費やしました。何層ものマクロと何百行もの特殊化クラスがあると、見栄えがよくありません。メタ プログラミングをより簡単にし、移植性を高めてくれるブースト ライブラリの作成者に対して、私は今まで以上に感謝しています。願わくば、C++0x がライブラリ作成者の生活も楽にしてくれることを願っています。

とにかく、ソリューションはシンプルでエレガントです。

最初の iter_fold は、null 型に依存できる反復子を指定する方法を理解できなかったため、私が望むものではありません。そこで、フォールドをいじって、次のことを見つけました。

typedef fold<Policies, Null, Cons<_1, _2> >::type MyPolicy;

これを機能させるには、Null 型と Cons の特殊化を提供する必要があります。

struct Null { };

template<class PolicyT>
struct Cons<Null, PolicyT> {
  static void init() { PolicyT::init(); }
  static void cleanup() { PolicyT::cleanup(); }
};
于 2008-11-04T03:16:44.630 に答える
1

実際のランタイムオブジェクトでinit関数を呼び出したいので、問題はメタ関数よりもむしろランタイム呼び出しだと思います。

次のように、mpl のランタイム アルゴリズムを試すことができます。

for_each<Policies>(InitPolicy());

struct InitPolicy() {
    template<class Policy>
    void operator() (Policy& p) { p.init_options(); }
};
于 2008-11-02T12:40:55.320 に答える
1

次のようなものを探していると思います:

typedef 
  iter_fold<
    Policies,
    begin<Policies>::type,
    Cons<_1,_2>
  >::type
  MyType;

また、コンパイル時にハードワイヤードされたベースの関数を呼び出すために、ある種の CRTP を組み込む場合は、inherit_linearly<>を調べることもできます。

于 2008-11-02T19:51:59.163 に答える