3

我有这个功能:

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

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

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

4

4 回答 4

4

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

您可以提供几个接受最多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<>().

于 2013-06-13T15:23:03.147 回答
1

如果你可以使用 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)));

PS 不要这样做:

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

您可以添加重载:

T *allocate(){ return allocate(boost::in_place()); }
于 2013-06-13T15:36:40.587 回答
1

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

如果您没有 C++11 功能,则可以伪造它,至少对于参数数量的设定限制。但这并不容易或漂亮。例如,请参阅boost::tuple.

于 2013-06-13T15:24:31.870 回答
0

如果您不想使用 vardic 模板,您可能需要对这个进行设计:

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

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

于 2013-06-13T15:40:57.060 回答