2008-11-02 93 views
6

我已经使用类似以下内容组成了我的申请策略:如何使用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(); 
    } 
    //... 
}; 

要编写策略:

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 

从本质上讲,缺点在这里构建一个类型列表。这非常简单。然而,typedef缺点是有点丑。这将是理想的具有政策组合可以做到这一点:

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 here。我确信这里的mpl专家是相当简单的。

在此先感谢。

回答

1

我认为你的问题比运行时调用要比元功能,因为你想调用实际运行时对象的init函数。

你可以尝试MPL的运行算法, 像:

for_each<Policies>(InitPolicy()); 

struct InitPolicy() { 
    template<class Policy> 
    void operator() (Policy& p) { p.init_options(); } 
}; 
+0

有一个小的bug你的榜样。这可以使这个例子起作用。我可以为每种方法使用for_each。但是我希望有一个可以传递的组合策略,即,我更喜欢在编译时执行命令,而不是使用for_each运行时执行。 – ididak 2008-11-02 17:26:08

+0

正如我所看到的,只能在编译时调用元函数,在编译时我看不到任何方法调用init_options()或任何其他普通函数。我知道你希望通过在运行时调用init_with来自动应用策略列表中的所有策略,这正是for_each所做的。请澄清 – tabdamage 2008-11-02 17:32:41

+0

目标是在编译时编写一个策略类,并按照我的原始示例执行该命令,实际的方法确实在运行时被调用,如MyCombinedPolicy :: init_options()等。 – ididak 2008-11-02 17:39:09

1

我认为你正在寻找的东西,如:

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

也可能想要查看inherit_linearly<>如果您插入某种CRTP来调用基地的功能在编译时硬连线。

9

由于没有人满意地回答了这个问题,我花了一些时间挖掘boost :: mpl源代码。男人,这与宏层和数百行专业化课程并不相称。我现在对boost库的作者更加欣赏,使我们能够更轻松,更便携地进行元编程。希望C++ 0x也会让库作家的生活更轻松。

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

首先iter_fold不是我想要的,因为我无法弄清楚如何指定一个可以被推断为空类型的迭代器。所以我折摆弄着,找了以下内容:

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

为了这个工作,我需要提供空类型和缺点专业化:

struct Null { }; 

template<class PolicyT> 
struct Cons<Null, PolicyT> { 
    static void init() { PolicyT::init(); } 
    static void cleanup() { PolicyT::cleanup(); } 
};