我使用了以下内容为我的应用程序编写策略:
政策类看起来像这样:
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 line有点难看。拥有可以做到这一点的策略组合器是理想的:
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专家来说是非常微不足道的。
提前致谢。
答案 0 :(得分:9)
由于没有人满意地回答这个问题,我花了一些时间深入研究了boost :: mpl来源。伙计,宏层和数百行专业化类并不漂亮。我现在更感谢boost库的作者使我们的元编程更容易,更便携。希望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(); }
};
答案 1 :(得分:1)
我认为你的问题是运行时调用而不是元函数,因为你想在实际的运行时对象上调用init函数。
你可以试试mpl的运行时算法, 喜欢:
for_each<Policies>(InitPolicy());
带
struct InitPolicy() {
template<class Policy>
void operator() (Policy& p) { p.init_options(); }
};
答案 2 :(得分:1)
我认为你正在寻找类似的东西:
typedef
iter_fold<
Policies,
begin<Policies>::type,
Cons<_1,_2>
>::type
MyType;
如果你使用某种CRTP来调用在编译时硬连接的基本函数,你也可能需要查看inherit_linearly<>。