2012-09-12 49 views
1

專門研究一個池類我有一個模板化的池類來管理一堆對象的生命週期。通常,它會根據需要調用new和delete,但我也可以傳遞一個create函數並銷燬函數。根據創建函數是否通過

現在,對於這個類的一些用戶,我希望有一個私有構造函數,並且只允許傳遞一個create/destroy函數。這會導致編譯錯誤,因爲即使未使用「新T」行仍在池類中。到目前爲止,我已經通過讓游泳池成爲有問題的課程的朋友來解決這個問題。這仍然會造成誤用的可能性(例如,通過手動創建特定對象的池並且不傳遞創建/銷燬函數),所以我想知道什麼是專門化池類的最佳方法,以便我可以擁有真正的私有不使用朋友的模板參數上的構造函數。

回答

0

需要你可以專注你的模板:

template <typename T, bool Constructible> 
struct Pool 
{ 
    T * make() 
    { 
     return maker(std::common_type<Constructible>()); 
    } 

    T * maker(std::common_type<false>) { return T::create(); } 

    T * maker(std::common_type<true>) { return new T(); } 
}; 

Pool<Foo, true> fooPool; // uses "new Foo();" 
Pool<Bar, false> barPool; // uses "Bar::create();" 
1

如果我正確理解你的意圖,我想我會做這樣的事情:如果用戶通過構造函數對象

template <class T> 
struct constructor { 
    T *make() { return new T; } 
    void destroy(T const *t) { delete t; } 
}; 

template <class T, class ctor = constructor<T> > 
class Pool { 
    ctor c; 
    // ... 
    T *t = c.make(): 

    // ... 

    c.destroy(t); 
}; 

,你的代碼使用它的make/destroy函數。如果他們沒有通過,則將使用constructor模板,其將使用newdelete

作爲一個小的變化,你可能更喜歡讓makedestroystatic成員函數,所以Pool內,你只需要使用ctor::make();ctor::destroy(t);

0

我相信這是最靈活的解決方案。這是基於特徵 - 就像其他答案一樣,但它使用起來非常簡單。如果您需要更改建築或銷燬,請放置專門的功能。

我的建議:

template <typename T> 
T* std_new() { return new T(); } 
template <typename T> 
void std_delete(T* p) { delete p; } 

template <typename T, T*(*Create_)() = std_new<T>, void(*Destroy_)(T*) = std_delete<T> > 
class Pool { 
public: 
    T* create() { return Create_(); } 
    void destroy(T* p) { Destroy_(p); } 
}; 

及其用法:

Pool<int> pi; 
int* new_int_7() { return new int(7); } 
Pool<int, new_int_7> pi7; 

要保持陣列在池:

template <typename T, int N> 
T* std_new_arr() { return new T[N](); } 
template <typename T> 
void std_delete_arr(T* p) { delete [] p; } 

Pool<int, std_new_arr<int, 6>, std_delete_arr<int> > piarr; 

如果使用一些標準集裝箱但是考慮與專門的allocato r(如果需要)可能是最佳選擇。