2010-04-08 82 views
3

我想寫一個通用的分配器類,它不釋放對象的內存時,它是免費的()'D,但它保留在隊列中,並返回一個以前分配的對象,如果新的請求。現在,我無法包裹頭腦的是如何在使用我的分配器時將參數傳遞給對象的構造函數(至少不使用可變參數模板即可)。我想出了看起來像這樣的alloc()函數:沒有可變參數模板的通用分配器類?

template <typename... T> 
inline T *alloc(const &T... args) { 
    T *p; 

    if (_free.empty()) { 
     p = new T(args...); 
    } else { 
     p = _free.front(); 
     _free.pop(); 

     // to call the ctor of T, we need to first call its DTor 
     p->~T(); 
     p = new(p) T(args...); 
    } 
    return p; 
} 

不過,我需要的代碼是與今天的C++(和舊版本不支持可變參數模板GCC)的兼容。是否有任何其他方式去傳遞任意數量的參數給對象構造函數?

回答

3

當你需要的目標,你需要提供僞可變參數模板前的C++ 0x編譯器,即你需要爲每個需要的參數數量提供了一個模板函數:

template<class T> 
T* alloc() { 
    /* ... */ 
} 

template<class T, class A0> 
T* alloc(const A0& a0) { 
    /* ... */ 
} 

/* ... */ 

您可以使用preprocessor metaprogramming雖然處理重複,例如通過使用Boost.Preprocessor或通過簡單的腳本生成函數。

以下是使用Boost.PP一個簡單的例子:

#include <boost/preprocessor/arithmetic/inc.hpp> 
#include <boost/preprocessor/repetition/enum_binary_params.hpp> 
#include <boost/preprocessor/repetition/enum_params.hpp> 

template<class T> 
T* alloc() { 
    return new T; 
} 

#define FUNCTION_ALLOC(z, N, _) \ 
    template<class T, BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), class T)> \ 
    T* alloc(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, BOOST_PP_INC(N), const T, &p)) { \ 
    return new T(\ 
     BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), p) \ 
    ); \ 
    } 

BOOST_PP_REPEAT(10, FUNCTION_ALLOC, ~) 

#undef FUNCTION_ALLOC 

這會產生你alloc()多達10個參數模板功能。

+0

可能促進幫助的嗎? – UncleBens 2010-04-08 14:07:59

+0

是的,Boost.PP幫助 - 我認爲@GMan有一個很好的例子,會嘗試挖掘它。 – 2010-04-08 14:10:02

+0

我做了很多Boost預處理器的東西,但是我不認爲我在網站上投入了太多。儘管Matthieu最近做了一個:http://stackoverflow.com/questions/2597586/simplifying-templates/2598283#2598283 – GManNickG 2010-04-08 15:06:50

0

問題的前C++ 11解決方案是隻提供一個簡單的alloc函數,它構造了它的參數副本。這是C++ 03分配器和所有容器工作20多年的方式。它應用到你的代碼就變成:

template <typename T> 
inline T *alloc(const &T arg) { 
    T *p; 

    if (_free.empty()) { 
     p = new T(arg); 
    } else { 
     p = _free.front(); 
     _free.pop(); 

     // to call the ctor of T, we need to first call its DTor 
     p->~T(); 
     p = new(p) T(arg); 
    } 
    return p; 
} 

然後你怎麼稱呼它爲:

// copy construct T into the allocator's memory: 
instance_of_your_allocator.alloc(T(1, 2, 3)); 

這種方法的缺點是,它需要一個拷貝構造函數是可用的,並且它的一個潛在的代價高昂的操作。

再舉一個例子:

vector<T> vec; 
vec.push_back(T(1, 2, 3)); // C++03 way, uses move cons-tor in C++11 if possible. 
vec.emplace_back(1, 2, 3); // C++11 way, constructs in-place 
相關問題