3

我希望能够在编译时强制执行特定类型只能用于创建具有自动存储持续时间的对象。

template<typename T, typename Alloc>
struct Array
{
    T* data; // owned resource
    Array(std::size_t size); // allocates via Alloc
    ~Array(); // deallocates via Alloc
};

typedef Array<int, AutoAllocator<int>> AutoArray;

void foo(AutoArray a) // ok
{
    AutoArray l = AutoArray(); // ok
    static AutoArray s; // error
    new AutoArray(); // error
    std::vector<AutoArray> v(1); // error
}

对此的应用将能够为 的实例所拥有的资源选择最佳分配策略AutoArray这个想法是具有自动存储持续时间的对象所需的资源分配模式与 LIFO 资源分配器兼容。

我可以使用什么方法在 C++ 中实现这一点?

编辑:次要目标是允许Array通过放入其中一个AutoAllocator或 default来透明地切换分配策略std::allocator

typedef Array<int, std::allocator<int>> DynamicArray;

假设有大量代码已经使用DynamicArray.

4

1 回答 1

2

这是无法做到的。考虑您创建了一个将其作为成员的类型。当编译器为该类型的构造函数生成代码时,它不知道对象是在哪里创建的,是堆栈中的完整对象,还是堆中的?

您需要用不同的思维方式解决您的问题,例如,您可以将分配器传递给对象的构造函数(就像BSL所做的那样),并且可能默认为安全分配器(基于 new-delete),然后对于那些LIFO 分配器是更好的选择的用例,用户可以显式请求它。

这与编译器错误不同,但它足够明显,可以在代码审查中检测到。

如果您真的对分配器的有趣用途感兴趣,您可能想看看标准库的 BSL 替代品,因为它允许传播到容器成员的多态分配器。在 BSL 世界中,您的示例将变为:

// Assume a blsma::Allocator implementing LIFO, Type uses that protocol
LifoAllocator alloc;       // implements the bslma::Allocator protocol
Type l(&alloc);            // by convention bslma::Allocator by pointer
static Type s;             // defaults to new-delete if not passed
new (&alloc) Type(&alloc); // both 'Type' and it's contents share the allocator
                           // if the lifetime makes sense, if not:
new Type;                  // not all objects need to use the same allocator
bsl::vector<Type> v(&alloc);
v.resize(1);               // nested object uses the allocator in the container

一般来说,使用分配器并不简单,您必须注意对象相对于彼此和分配器的相对生命周期。

于 2013-10-08T16:40:57.127 回答