如果我为容器使用自定义分配器,我不喜欢我必须重复包含的typename:
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;
第二行是根据标准的未定义行为,但大多数实现会将分配器重新绑定到正确的类型.
我的问题是,鉴于容器和分配器是同一类型的要求,为什么没有一些标准机制来强制执行(或完全避免它)并消除用户错误的可能性?
例如,标准可以强制使用重新绑定(以有效地使allocator模板参数冗余),或者可以使用类似下面的模式,因此用户只提到包含的typename一次:
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;
}
最佳答案 这是一个很好的问题,您的建议是标准方案的一种可能替代方案.另一种方法是使用模板模板参数:
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;
在模板模板参数是语言的一部分之前设计了allocator接口,因此这不是一个选项.
如果今天要设计分配器API,有很多事情会以不同的方式完成,不幸的是我们仍然坚持我们拥有的(以及尝试以半兼容的方式扩展它所带来的持续复杂性).