1

我有一个模板池类来管理一堆对象的生命周期。通常,它会根据需要调用new和delete,但我也可以传入一个create函数和destroy函数。

现在,对于此类的某些用户,我希望有一个私有构造函数,并且只允许传入创建/销毁函数。这会导致编译错误,因为“new T”行仍然在池类中,即使它没有被使用。到目前为止,我已经通过让 pool 成为相关班级的朋友来解决这个问题。这仍然留下了滥用的可能性(例如,通过手动创建特定对象的池而不传递创建/销毁函数),所以我想知道专门化池类的最佳方法是什么,这样我就可以拥有真正的私有在其模板参数上的构造函数而不使用朋友。

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 函数。如果他们没有通过一个,那么将使用模板,该constructor模板将使用newand delete

作为一个小变化,您可能更喜欢将makeanddestroy作为static成员函数,因此在 内部Pool,您只需使用ctor::make();and 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 回答