1

オブジェクトの束の有効期間を管理するテンプレート化されたプール クラスがあります。通常、必要に応じて new と delete を呼び出しますが、create 関数と destroy 関数を渡すこともできます。

さて、このクラスの一部のユーザーには、プライベート コンストラクターが必要であり、create / destroy 関数の受け渡しのみを許可したいと考えています。これにより、コンパイル エラーが発生します。これは、"new T" 行が使用されていないにもかかわらず、まだプール クラスにあるためです。これまでのところ、プールを問題のクラスのフレンドにすることでこれを解決しました。これはまだ誤用の可能性を残しています (たとえば、特定のオブジェクトのプールを手動で作成し、作成/破棄関数を渡さないなど)。そのため、プール クラスを特殊化して真のプライベートを持つことができるようにする最善の方法は何か疑問に思っています。フレンドを使用せずにテンプレート引数のコンストラクター。

4

3 に答える 3

1

あなたの意図を正しく理解しているなら、私は次のようなことをすると思います:

template <class T>
struct constructor { 
    T *make() { return new T; }
    void destroy(T const *t) { delete t; }
};

template <class T, class ctor = constructor<T> >
class Pool {
    ctor c; 
    // ...
    T *t = c.make():

    // ...

    c.destroy(t);
};

ユーザーがコンストラクター オブジェクトを渡すと、コードはその make/destroy 関数を使用します。それらが 1 つを渡さない場合、constructorテンプレートが使用されます。これは and を使用newdeleteます。

マイナー バリエーションとして、メンバー関数としてmakeandを使用することをお勧めします。したがって、 の内部では、 and を使用するだけです。destroystaticPoolctor::make();ctor::destroy(t);

于 2012-09-12T22:39:09.860 に答える
0

これが最も柔軟なソリューションだと思います。これは、他の回答と同様に特性に基づいていますが、非常に使いやすいです。建設や破壊を変更する必要がある場合は、専門の機能を配置するだけです。

わたしの提案:

template <typename T>
T* std_new() { return new T(); }
template <typename T>
void std_delete(T* p) { delete p; }

template <typename T, T*(*Create_)() = std_new<T>, void(*Destroy_)(T*) = std_delete<T> >
class Pool {
public:
   T* create() { return Create_(); }
   void destroy(T* p) { Destroy_(p); }
};

そしてその使用法:

Pool<int> pi;
int* new_int_7() { return new int(7); }
Pool<int, new_int_7> pi7;

プールに配列を保持したい:

template <typename T, int N>
T* std_new_arr() { return new T[N](); }
template <typename T>
void std_delete_arr(T* p) { delete [] p; }

Pool<int, std_new_arr<int, 6>, std_delete_arr<int> > piarr;

ただし、(必要に応じて)専用のアロケータを備えた標準のコンテナを使用することが最良の選択であるかどうかを検討してください。

于 2012-09-13T01:24:15.863 に答える
0

必要に応じてテンプレートを特殊化できます。

template <typename T, bool Constructible>
struct Pool
{
    T * make()
    {
        return maker(std::common_type<Constructible>());
    }

    T * maker(std::common_type<false>) { return T::create(); }

    T * maker(std::common_type<true>)  { return new T(); }
};

Pool<Foo, true> fooPool;    // uses "new Foo();"
Pool<Bar, false> barPool;   // uses "Bar::create();"
于 2012-09-12T22:18:34.533 に答える