2017-08-09 62 views
0

我正在編寫一個C++庫,所有類都使用工廠模式,即具有私有的空構造函數和私有的void init()函數,它可以進行實例的實際初始化。可以由用戶庫進行實例化的類有一個公共靜態create()函數執行以下操作:使用宏以工廠模式樣式替換「create()」函數API

static Class* create(int arg1, int arg2) { 
    Class* ret = new Class(); 
    ret->init(arg1, arg2); 
    return ret; 
} 

也有幾類,其不得從庫外面被實例化,所以他們不提供公共create()

這些「內部類」確實有相互之間的一些關係friend,這樣他們就可以實例對方。假設我想寫儘可能少的代碼可能,所以我想,以避免聲明和定義所有的內部類私人create()功能,但我也想避免編寫

InternalClass* foo = new InternalClass(); 
foo->init(); 

所有的時間內類被實例化。相反,它會是不錯的一個(模板)函數或宏,它可以創建任何內部類只需要一行代碼,如

template<class T, typename ...Args> inline T* create(Args... args) { 
    T* ret = new T(); 
    ret->init(args...); 
    return ret; 
} 

與上述功能(其將被定義爲在一個全局共享頭一個獨立的功能,因此,inline關鍵字)的問題是,它繞過了類之間的friend聲明並且因此將不會編譯。

另一方面,宏的問題在於,只要在宏內部有語句ret->init(),它就不能「返回」指向該實例的指針,因此使用類似以下的宏將不會可能:

InternalClass* foo = CREATE(InternalClass, arg1, arg2); 

最後,我的問題是:

是它在某種程度上可以創建一個可以在上面的方式調用(和不改變的所有init()函數的返回類型一類的宏類型的指針,這的確會允許:#define CREATE(T, ...) (new T())->init(__VA_ARGS__))?

(請注意,這更是一個學術不是我已經實現與私營create()功能的解決方案,這工作完全正常,似乎是「最乾淨」解決方案實用問題,我只是想知道是否有可能已經與宏的解決方案,太...)

+2

我們用init嗎?爲什麼不在構造函數中進行初始化?另外,你的工廠方法的返回類型實際上是一樣的類,所以這家工廠是沒用的。 – SergeyA

+0

如果你真的想要使用宏(你幾乎肯定不會),你可能需要像GCC的[語句表達式](https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs)。 html):#define CREATE(T,...)({auto * ret = new T; ret-> init(__ VA_ARGS__); ret;})'' – Justin

回答

1

您可以混合使用這兩個模板和宏:

template <typename T, typename InitF, typename... Args> 
T* CreateImpl(T* t, InitF init, Args&&...args) 
{ 
    (t->*init)(std::forward<Args>(args)...); 
    return t; 
} 

和宏(到f向前的私人東西)

// I assume no overloads of T::init 
#define CREATE(T, ...) CreateImpl(new T(), &T::init, __VA_ARGS__)