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

时间:2013-06-13 15:16:14

标签: c++ templates

我有这个功能:

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

现在,它可以很好地创建具有默认构造函数的对象,但是如何创建需要传递新参数的对象?

我知道可以使用C ++ 11的可变参数template来实现,但是如果没有C ++ 11功能,我怎么能这样做呢? (显然我的VS2012版本还不支持这个功能,但我想知道如果没有这个功能,即使升级会修复它也不知道怎么做)

4 个答案:

答案 0 :(得分:4)

没有替代可变参数模板的语言功能(当然,否则它们不会被发明)。

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

除了你的nullary函数模板:

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<>()

答案 1 :(得分:1)

这不仅仅是您需要的可变参数模板,还有C ++ 11的完美转发功能。

如果您没有C ++ 11功能,可以伪造它,至少对参数数量设置限制。但这并不容易或漂亮。有关示例,请参阅boost::tuple的提升实现。

答案 2 :(得分:1)

如果您使用提升,则可以使用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)));

<强> PS 不这样做:

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

您可以添加重载:

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

答案 3 :(得分:0)

如果您不想使用varadic模板,则可能需要对此进行设计点击:

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;
}

不确定是否会编译,但你明白了。