Using custom allocator for AllocatorAwareContainer data members of a class

坚强是说给别人听的谎言 提交于 2020-01-03 00:39:08

问题


Given a non-stateless custom allocator A (say, arena allocator, binded to some contiguous memory chunk of runtime-known size) and class S, containing a fileds of AllocatorAwareContainer types:

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

I want to use A for a subset (or even for all) AllocatorAwareContainer fields of class S. It is clear, that I should to provide one another template parameter for class S and change types of all the interesting data members correspondingly as follows:

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;
};

What are changes in present constructors and additional constructors (assume A is not DefaultConstructible and any other possible restrictions may holds) should I made?

Should I store allocator A in additional field of class S?

What is a general tips to use custom allocators for classes?


回答1:


I'm used to using the containers from 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). This approach gets nicely rid of the std::rebind-dance which complicates matters in an area which is already relatively complicated. Otherwise, I think the concepts translate. I don't have experience using allocators with standard library containers.

There are two fundamental rules for the use of allocators which work well in practice:

  1. The allocator of an object does not change once constructed.
  2. Every allocator-aware type shall pass an allocator received as constructor argument to all allocator-aware members.

The second rule implies that constructors of classes need to take care of all their members. Where the member type is known it is fairly straight forward to determine whether an allocator is needed and how it is to be constructed. When the member type is generic in some form, i.e., it depends on a template argument in some form, it is generally not known whether an allocator is needed.

When it is unclear whether a member needs to receive an allocator the approach used when using bsl is to hold a wrapped member. More specifically, the members would hold a bslalg::ConstructorProxy<T> which would determine statically with T supports constructors taking allocators and appropriate passes an allocator or not.



来源:https://stackoverflow.com/questions/32945557/using-custom-allocator-for-allocatorawarecontainer-data-members-of-a-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!