2017-08-09 76 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__)