将构造函数参数传递给模板函数工厂

Passing constructor parameters to a template function factory

本文关键字:函数 工厂 构造函数 参数传递      更新时间:2023-10-16

我有这个函数:

template <class T> 
T *allocate()
{
    T *obj = new(top) T();
    top += sizeof(T);
    return obj;
}

现在,用默认构造函数创建对象工作得很好,但是我如何创建需要传递新参数的对象呢?

我知道它可以使用c++ 11的可变template实现,但如果没有c++ 11的功能,我怎么能做到这一点?(显然我的VS2012版本还不支持这个功能,但我想知道如何做到这一点,没有这个功能,即使升级将修复它)

没有一个语言特性可以取代可变模板(当然,否则它们也不会被发明)。

您可以提供几个接受最多N参数的重载(对于N的合理选择)。每个重载都将其参数完美地转发给T的构造函数。

所以除了你的虚函数模板:

template <class T>
T *allocate()
{
    T *obj = new(top) T();
    top += sizeof(T);
    return obj;
}

你将有一个一元函数模板:

template <class T, class P1>
T *allocate(P1&& p1)
{
    T *obj = new(top) T(std::forward<P1>(p1));
    top += sizeof(T);
    return obj;
}

二进制函数模板:

template <class T, class P1, class P2>
T *allocate(P1&& p1, P2&& p2)
{
    T *obj = new(top) T(std::forward<P1>(p1), std::forward<P2>(p2));
    top += sizeof(T);
    return obj;
}
三元函数模板:
template <class T, class P1, class P2, class P3>
T *allocate(P1&& p1, P2&& p2, P3&& p3)
{
    T *obj = new(top) T(std::forward<P1>(p1), std::forward<P2>(p2), 
                        std::forward<P3>(p3));
    top += sizeof(T);
    return obj;
}

等等(你明白了)。如果您介意代码复制,可以使用一些宏来减少痛苦——但它们并不能消除痛苦,尤其是在您不喜欢宏的情况下。

别忘了:

#include <utility>

访问std::forward<>()

你需要的不仅仅是可变模板,还有c++ 11完美的转发能力。

如果你没有c++ 11的功能,它是可能的,至少对参数的数量设置限制。但这并不容易,也不漂亮。例如,请参见boost::tuple的boost实现。

如果您可以使用boost,您可以使用boost::in_place_factory代替http://www.boost.org/doc/libs/1_35_0/libs/utility/in_place_factories.html

template <class InplaceFactory> 
T *allocate(InplaceFactory const & fac)
{
    T *obj = reinterpret_cast<T*>(top);
    fac.template apply<T>(obj)
    top += sizeof(T);
    return obj;
}

和使用:

T * a = allocate(boost::in_place(val, boost::ref(ref_value)));

p 不这样做:

T * a = allocate(boost::in_place());

你可以添加重载:

T *allocate(){ return allocate(boost::in_place()); }

如果你不想使用可变模板,你可能需要在设计上受到打击:

struct empty {};
template<typename ObjectType,unsigned int ARG_LENGTH = 0,
         typename arg0=empty,
         typename arg1=empty,
         typename arg2=empty,
         typename arg3=empty,
         typename arg4=empty>
ObjectType* allocate(const arg0& a0, 
                     const arg1& a1,
                     const arg2& a2,
                     const arg3& a3,
                     const arg4& a4){
   ObjectType * obj = 0;
   switch(ARG_LENGTH){
     case 0: obj = new(top) ObjectType();break;
     case 1: obj = new(top) ObjectType(arg0);break;
     case 2: obj = new(top) ObjectType(arg0,arg1);break;
     case 3: obj = new(top) ObjectType(arg0,arg1,arg2);break;
     case 4: obj = new(top) ObjectType(arg0,arg1,arg2,arg3); break;
     default: obj = new(top) ObjectType(); break;
   }
   top += sizeof(T);
   return obj;
}

不确定是否可以编译,但你知道的。