2008-11-02 44 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(); } 
};