2012-10-23 27 views
0

我有三個類遵循相同的概念類,但在用於存儲的底層數據結構上有所不同。作爲一個例子,下面給出了三個類。我們如何使用boost :: mpl實現Builder設計模式?

template< typename T > 
class A{ 
    std::vector<T> storage; 
    //etc 
}; 

template<> 
class A<bool>{ 
    boost::dynamic_bitset<> storage; 
    //etc 
}; 

class B{ 
    ComplexUDT storage; 
    //etc 
}; 

A類是使用向量的泛型類。爲了避免使用vector<bool>,我們提供了A類的完全專業化,它使用boost::dynamic_bitset<>作爲底層存儲。最後,B類使用用戶定義的數據類型作爲存儲。上述設計導致了代碼中的冗餘。要消除這種冗餘,我想用升壓:: MPL

template< typename T > 
class vec_impl{ 
    std::vector<T> storage; 
    //impl of methods 
}; 

class bitset_impl{ 
    boost::dynamic_bitset<> storage; 
    //impl of methods 
}; 

class udt_impl{ 
    ComplexUDT storage; 
    //impl of methods 
}; 

template<Derived,Storage> 
class main_class_gen{ 
    typedef typename boost::mpl::if_<is_complexudt<Storage>, 
             udt_impl, 
             typename boost::mpl::if_< is_bool<Storage>, 
                   bitset_impl, 
                   vec_impl<Storage> >::type >::type type 
}; 

class main_class: 
        public main_class_gen< main_class<Storage>,Storage >::type{ 
     //impl. of methods 
}; 

如boost ::,dynamic_bitset不一個容器模型的一些類方法的實現比vector類不同。複雜的UDT基礎類與其他兩個類非常不同,但確實有一些常見的小代碼段。但目前的重構方法仍然會導致代碼冗餘。概念類中提到的所有方法都必須在每個實現中實現。

所以我的問題是兩倍。

  1. 我們如何使用boost :: mpl實現Builder設計模式?
  2. 在上面的例子中,CRTP會以什麼方式提供幫助?

回答

1

如果我正確理解你想要做的事情,這可能會爲你工作:

首先,每個容器必須實現相同的接口。根據需要創建(對於ComplexUDT例如)適配器:

struct AdapterUDT { 
    typedef double const_reference; 
    void push_back(double); 
    private: ComplexUDT complexUDT; 
}; 

雖然一般不推薦它,你可以繼承來,dynamic_bitset添加/修改功能。請注意,您不能多形地使用它,因爲它缺少虛擬析構函數。確保它不在其他地方使用。

struct AdapterBitset : dynamic_bitset<> { // not recommended 
    typedef my_biterator iterator; 
    AdapterBitset(int n) : dynamic_bitset(n) {} 
    iterator begin(); 
}; 

定義性狀類型與集裝箱相關聯:

template<typename T> struct Trait { 
    typedef vector<T> type; 
}; 
template<> struct Trait<bool> { 
    typedef dynamic_bitset<> type; 
}; 

創建一個實現接口的存儲模板(減去容器):

template<class T, class Derived> struct Base { 
    typedef Base<T,Derived> base_t; 
    typedef typename Trait<T>::type container_type; 
    typedef typename container_type::const_reference const_reference; 
    void append(const_reference value) { 
    // static polymorphism to access the standardized containers/adapters 
    static_cast<Derived*>(this)->container.push_back(value); 
    } 
    // etc 
}; 

由於需要構造基於在存儲類型上,存儲模板必須管理實例:

template<class T> struct Storage : Base<T,Storage<T>> { 
    friend struct base_t; 
    protected: container_type container; 
}; 
// specialize for types with ctor arguments: 
template<> struct Storage<bool> : Base<bool,Storage<bool>> { 
    friend struct base_t; 
    Storage(int bits) : container(bits) {} 
    protected: container_type container; 
}; 

用例:

Storage<int> astore; // generic version uses default ctor 
astore.append(314); 
Storage<bool> bstore(7); // bool specialization requires an int 
bstore.append(true); 

這應該減少最冗餘代碼。如果這不是你想要的,我需要一個你想解決的問題的更具體的例子。

+0

謝謝您的回覆!這確實是一種更清晰的實現方式,但是「ComplexUDT」具有參數化的ctors。建設的代表團需要一個工廠方法,但不幸的是,它不能在'GenericStorage'的Ctor中給出,或者有另一種我不知道的方式? –

+0

我的更新補遺:如果您的編譯器支持C++ 11,您可以爲構造函數使用可變參數模板。 –

+0

@Samrat我修改了我的答案。請檢查一下是否更像您的想法。 –