如何使用boost :: mpl来编写策略?

idi*_*dak 6 c++ templates metaprogramming boost-mpl

我使用类似下面的内容为我的应用程序编写策略:

策略类如下所示:

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();
  }
  //...
};
Run Code Online (Sandbox Code Playgroud)

撰写政策:

typedef Cons<Policy1, Cons<Policy2, Cons<Policy3, Policy4> > > MyPolicy;
Run Code Online (Sandbox Code Playgroud)

要使用MyPolicy:

init_with<MyPolicy>(...);
//...
cleanup_with<MyPolicy>(...);
Run Code Online (Sandbox Code Playgroud)

他们打电话的地方:

MyPolicy::init_options(); // calls Policy1 to 4's init in order
Run Code Online (Sandbox Code Playgroud)

MyPolicy::cleanup(); // calls Policy1 to 4's cleanup in reverse order
Run Code Online (Sandbox Code Playgroud)

从本质上讲,Cons在这里构造一个类型列表.这很直接.然而,typedef cons line有点难看.拥有可以执行此操作的策略组合器是理想的:

typedef CombinePolicy<Policy1, Policy2, Policy3, Policy4> MyPolicy;
Run Code Online (Sandbox Code Playgroud)

由于我们可以拥有任意数量的策略,因此CombinePolicy在C++ 0x中需要可变参数模板支持,这只能在前沿编译器中通过实验获得.然而,似乎boost:mpl库通过使用一堆预处理技巧解决/解决了这个问题.我我可以使用类似的东西:

typedef mpl::list<Policy, Policy2, Policy3, Policy4> Policies;
Run Code Online (Sandbox Code Playgroud)

然后打电话:

init_with<Policies>(...);
Run Code Online (Sandbox Code Playgroud)

然后使用:

typedef iter_fold<Policies, begin<Policies>::type,
                  some_magic_lambda_expression>::type MyPolicy;
Run Code Online (Sandbox Code Playgroud)

显然,我在这里找出some_magic_lambda_expression有点麻烦.我相信这对mpl专家来说是非常微不足道的.

提前致谢.

idi*_*dak 9

由于没有人满意地回答这个问题,我花了一些时间深入研究了boost :: mpl源代码.伙计,宏层和数百行专业化类并不漂亮.我现在更感谢boost库的作者使我们的元编程更容易,更便携.希望C++ 0x也能让图书馆作家的生活更轻松.

无论如何,解决方案变得简单而优雅.

首先iter_fold不是我想要的,因为我无法弄清楚如何指定一个可以被引用为null类型的迭代器.所以我摆弄折叠并找到以下内容:

typedef fold<Policies, Null, Cons<_1, _2> >::type MyPolicy;
Run Code Online (Sandbox Code Playgroud)

为了使其工作,我需要提供Null类型和Cons的特化:

struct Null { };

template<class PolicyT>
struct Cons<Null, PolicyT> {
  static void init() { PolicyT::init(); }
  static void cleanup() { PolicyT::cleanup(); }
};
Run Code Online (Sandbox Code Playgroud)


tab*_*age 1

我认为您的问题是运行时调用而不是元函数,因为您想在实际运行时对象上调用 init 函数。

您可以尝试 mpl 的运行时算法,例如:

for_each<Policies>(InitPolicy());
Run Code Online (Sandbox Code Playgroud)

struct InitPolicy() {
    template<class Policy>
    void operator() (Policy& p) { p.init_options(); }
};
Run Code Online (Sandbox Code Playgroud)