【问题标题】:Why do container allocators need to specify the type they're allocating?为什么容器分配器需要指定它们分配的类型?
【发布时间】:2014-04-07 09:38:51
【问题描述】:

如果我为容器使用自定义分配器,我不喜欢重复包含的类型名:

template<typename T, size_t MyAllocatorArgument>
struct MyAllocator : public std::allocator<T>
{
    // ... Usual allocator implementation
};

typedef std::vector<int, MyAllocator<int, 42>> int_container;
typedef std::vector<int, MyAllocator<long, 12>> int_container_wrong_allocator;

根据标准,第二行是未定义的行为,尽管大多数实现会将分配器rebind 分配到正确的类型。

我的问题是,鉴于容器和分配器必须为同一类型,为什么没有一些标准机制来强制执行(或完全避免)并消除用户错误的可能性?

例如,标准可以强制使用rebind(以有效地使分配器模板参数变得多余),或者可以使用如下模式,以便用户只提及一次包含的类型名:

template<size_t MyAllocatorArgument>
struct MyAllocator
{
    // This would be something every allocator is required to expose.
    template<typename T>
    struct TypedAllocator : public std::allocator<T>
    {
        // This is where the normal implementation of the allocator would go.
        // allocate, deallocate etc.
    };
};

template<typename T, typename UntypedAllocator>
struct Container
{
    // All containers would do this to get the actual allocator type they would use.
    typedef typename UntypedAllocator::template TypedAllocator<T> TypedAllocator;

    Container() : m_allocator(TypedAllocator()) {}

    void useAllocator()
    {
        m_allocator.allocate();
        // ... or whatever else containers need to do with allocators.
    }

    TypedAllocator m_allocator;
};

void allocator_test()
{
    // Allocated type name isn't mentioned at point of use of container;
    // only once for the container. The container does all the work.
    Container<int, MyAllocator<42>> c1;
}

【问题讨论】:

  • 即使使用rebind,作者仍然可以使用模板参数为不同的客户端类型提供不同的分配器专业化。
  • @KerrekSB 问题是“鉴于容器和分配器必须为同一类型,为什么没有一些标准机制来强制执行(或完全避免)和消除用户错误的可能性?”所以你仍然可以创建一个带有分配器的vector for double
  • 如果 B 派生自 A,allocator&lt;A&gt; 可以潜在地用于分配 Bs。容器和分配器类型之间的对应关系似乎很自然,但(对我来说)很难说是否有必要.

标签: c++ stl allocator c++-standard-library


【解决方案1】:

这是一个很好的问题,您的建议是标准方案的一种可能替代方案。另一种是使用模板模板参数:

template<typename T>
class AnAllocator
{ ... };

template<typename T, template <typename> class Alloc = std::allocator>
class Vector
{
  typedef Alloc<T> allocator_type;
  ...
};

Vector<int, AnAllocator> v;

分配器接口是在模板模板参数成为语言的一部分之前设计的,所以这不是一个选项。

如果要在今天设计分配器 API,很多事情都会有所不同,不幸的是,我们坚持使用现有的(以及尝试以半兼容方式扩展它而导致的持续复杂性) .

【讨论】:

  • 哇哦,我怎么不知道模板模板参数?就在你认为你懂一门语言的时候,嗯?很好的解决方案,一般来说都是很好的答案。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-04
  • 1970-01-01
  • 2019-04-09
  • 2012-06-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多