On 01/05/18 19:10, Nicol Bolas wrote:
>
> According to P0174
> <
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0174r0#2.4>:
>
> > std::allocator<void> is defined so that various template rebinding
> tricks could work in the original C++98 library, but it is not an actual
> allocator, as it lacks both allocate and deallocate member functions,
> which cannot be synthesized by default from allocator_traits. That need
> went away with C++11 and the void_pointer and const_void_pointer type
> aliases in allocator_traits. However, we continue to specify it in order
> to avoid breaking old code that has not yet been upgraded to support
> generic allocators, per C++11.
>
> Essentially, I interpret this as them saying that the Allocator concept
> allocates/objects/, not memory. As such, `std::allocator<void>` is a
> nonsense type; `void` is an incomplete type and therefore cannot be
> allocated.
Allocators do allocate memory separately from creating objects. But it
is true that `std::allocator<void>` was not meant to be used to allocate
memory or create objects; my intent is not to make that possible.
Instead, `std::allocator<void>` communicates the "kind" of the allocator
to use for allocating whatever objects the container needs to.
I would never expect the container to use `std::allocator<void>` (or
`std::allocator<T>`) directly; instead I would expect the container to
always rebind the allocator as it sees fit.
> By deprecating the specialization, it makes it clear that `void`
> allocators are not supposed to be used. You may view this specialization
> as "the *only* one that makes sense", but that's not how it is meant to
> be used. The fact that a different allocator specialization may be used
> is essentially an implementation detail.
>
> Also, aren't node-based containers still required to use
> `allocator<value_type>` to//construct and destroy the `value_type`
> contents of their nodes? If so, then passing an `allocator<T>` still
> makes plenty of sense.
First, even if they must use `allocator<value_type>` to create values,
they also must allocate and create nodes using `allocator<node_type>`,
so they must rebind the allocator anyway. I don't think that requiring
to use `allocator<value_type>` is reasonable though as it offers no
advantage.
Second, whatever allocator specializations the container use internally
is rightfully an implementation detail. That is why requiring
`allocator<T>` in the container's template arguments makes no sense and
`allocator<void>` makes more sense as it avoids duplication. It makes
yet more sense for user's types that allocate multiple objects of
different types with no single `value_type`.