Why do distribution containers need to specify the type they allocate?

I don’t like that I need to repeat the contained type name if I use a special dispenser for the container:

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;

The second line is the undefined behavior in accordance with the standard, although in most implementations the rebinddistributor must be correct.

My question is that a container and a dispenser require a requirement for the same type, why is there no standard mechanism for its enforcement (or its complete elimination) and elimination of a potential user error?

For example, the standard may specify what rebindwill be used (to effectively make the dispenser template parameter redundant), or you can use a template similar to the one below, so the user only mentions the same name only once:

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;
}
+4
source share
1 answer

This is a good question, and your suggestion is one of the possible alternatives to the standard scheme. Another would be to use template template options:

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;

The dispenser interface was developed before the template template parameters were part of the language, so this is not an option.

, -, API- , , , ( , - ).

+2

Source: https://habr.com/ru/post/1535330/


All Articles