std::list
is parameterized by an allocator type, which it presumably rebinds in order to allocate list nodes rather than T
s. So what does it do with the object of allocator type passed to the constructor?
template <class T, class Alloc = std::allocator<T>>
class list
{
class node { ... T element; ... };
using real_alloc =
typename std::allocator_traits<Alloc>::template rebind_alloc<node>;
real_alloc m_allocator;
public:
list(const Alloc&);
};
In the above code, we need to initialize m_allocator
to a node allocator, but the constructor is given a T
allocator. Do we just drop the T
allocator on the floor, or do we use it somehow?
Since C++11
allocators can be stateful. You want to construct your internal allocator using the user supplied one. An Allocator is explicitely required to be constructible from typename std::allocator_traits<Alloc>::template rebind_alloc<U>
.
Implementations of list constructor should look like this:
template<class T, class Alloc>
class list
{
struct node_type {/*etc*/}; //internal
using allocator_type_internal = typename std::allocator_traits<Alloc>::template rebind_alloc<node_type>;
// etc.
allocator_type_internal m_allocator; //Note we use allocator_type, not Alloc.
};
list::list(const Alloc& alloc ) :
m_allocator(alloc)
{ /* initialize sentinel node, etc. */ }
Although a good implementation would use empty-base optimization for the allocator.
The T
allocator is still used to construct()
and destroy()
the T
portion of the internal nodes. Using these operations may be necessary to add custom arguments during construction, eg, optionally forward a suitable allocator argument to the constructed objects.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.