I don't like that I have to repeat the contained typename if I use a custom allocator for a 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 undefined behaviour according to the standard, though most implementations will rebind
the allocator to the correct type.
My question is, given that it's a requirement for the container and allocator to be for the same type, why is there not some standard machinery in place to enforce this (or avoid it entirely) and remove the potential for user error?
For example, the standard could mandate that rebind
does get used (to effectively make the allocator template parameter redundant), or a pattern like the below could be used so the user only mentions the contained typename 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;
}