我一直用C ++编写内存管理器,并且一直使用宏代替传统的new
调用。这背后的动力是双重的:我需要捕获有关所请求分配的类型信息,并且我想生成干净的语法。对于宏来说,这是一项艰巨的任务。但这就是我想出的:
#define anew( TYPE ) new ( Allocator::Instance( )->Allocate<TYPE>( ) ) TYPE
它调用分配器在内存池中为TYPE
类型的对象(相对于宏)创建一个点。然后它使用Allocate
返回的指针作为放置new
的参数,允许构造函数在这个刚刚“分配”的内存块上运行。到目前为止有道理。因此,在正常使用中,这是它扩展的方式:
Obj* a = anew( Obj )( );
Obj* a = new ( Allocator::Instance( )->Allocate<Obj>( ) ) Obj( );
这很棒!但是当我尝试将它与具有多个参数的模板化类一起使用时,它会爆炸(我的意思是它会产生错误)。
Obj<int, bool>* a = anew( Obj<int, bool> )( );
这抱怨没有足够的类型参数提供给模板参数。经过一些戳之后,我明白这是因为模板参数中的逗号。在这种情况下,如何解决此问题?
更好的是,还有更好的方法吗?我认为将它作为一个宏是有意义的,因为我真的只想在这里进行一些直接文本替换。但是,从以不同的方式解决这个问题,我能获得什么吗是否可以在不使用宏的情况下完成此操作?我尝试过这条路线,出现的问题是调用构造函数。以下代码无效,但它会很好:
Obj* a = anew<Obj>( );
其中括号只能对应给定类型的有效构造函数。
非常感谢任何帮助。谢谢!
[编辑]
虽然Variadic Macros也解决了我的问题,但我在下面选择的答案是我认为是我问题的最佳C ++解决方案。谢谢大家这么快解决这个问题。
答案 0 :(得分:7)
使用C ++ 11,您可以这样做:
template <typename T,typename... Args>
T* anew(Args&&... args)
{
return new(Allocator::Instance()->Allocate<T>()) T(std::forward<Args>(args)...);
}
现在您可以使用此表单:
Obj* a = anew<Obj>( );
并将参数的任何内容(或任何内容)传递给构造函数。
std::forward
是允许参数从一个函数转发到另一个函数的一般机制。它依赖于右值引用的参数和参数与模板的折叠,使其成为正确有效地传递左值和右值的地方。结合可变参数,这允许以这种方式完美地转发任意数量的参数。