为 class 的 AllocatorAwareContainer 数据成员使用自定义分配器

Using custom allocator for AllocatorAwareContainer data members of a class

给定一个非无状态的自定义分配器 A(例如,arena 分配器,绑定到一些运行时已知大小的连续内存块)和 class S,包含一个字段AllocatorAwareContainer 类型:

struct S
{
    A() = default;
    // another c-tors
    std::vector< T > v;
    std::shared_ptr< U > s;
};

我想将 A 用于 class S 的子集(甚至全部)AllocatorAwareContainer 字段。很明显,我应该为 class S 提供另一个模板参数,并相应地更改所有有趣数据成员的类型,如下所示:

template< typename A = std::allocator< void > >
struct S
{
    // c-tors
    template< typename X >
    using allocator = typename std::allocator_traits< A >::template rebind< X >::other;
    std::vector< T, allocator< T > > v;
    std::shared_ptr< U, allocator< U > > s;
};

我应该对现有构造函数和附加构造函数进行哪些更改(假设 A 不是 DefaultConstructible 并且可能存在任何其他可能的限制)?

我应该将分配器 A 存储在 class S 的附加字段中吗?

为 classes 使用自定义分配器的一般技巧是什么?

我习惯使用 bsl which are allocator-aware and to creating allocator-aware classes. The primary difference to the standard containers and their allocator use is that bsl uses a pointer to the allocator base class (bslma::Allocator) 的容器。这种方法很好地摆脱了 std::rebind-dance,它使已经相对复杂的区域的事情变得复杂。否则,我认为这些概念会翻译。我没有将分配器与标准库容器一起使用的经验。

在实践中使用分配器有两个基本规则:

  1. 对象的分配器在构建后不会改变。
  2. 每个分配器感知类型都应将作为构造函数参数接收的分配器传递给所有分配器感知成员。

第二条规则意味着 类 的构造函数需要照顾它们的所有成员。在已知成员类型的情况下,可以相当直接地确定是否需要分配器以及如何构造分配器。当成员类型在某种形式下是通用的,即它依赖于某种形式的模板参数时,通常不知道是否需要分配器。

当不清楚成员是否需要接收分配器时,使用 bsl is to hold a wrapped member. More specifically, the members would hold a bslalg::ConstructorProxy<T> 时使用的方法将静态确定 T 支持采用分配器的构造函数并适当地传递分配器。