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

必要なのは可変個引数テンプレートだけではなく、C++11 の完全な転送機能も必要です。

C++11 の機能を持っていない場合、少なくともパラメーターの数に設定された制限については、それを偽造することができます。しかし、それは簡単でもきれいでもありません。例については、のブースト実装を参照してくださいboost::tuple

于 2013-06-13T15:24:31.870 に答える
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()); }
于 2013-06-13T15:36:40.587 に答える
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;
}

それがコンパイルされるかどうかはわかりませんが、アイデアは得られます。

于 2013-06-13T15:40:57.060 に答える