[/ Copyright 2020-2022 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) ] [section allocator_access] [simplesect Authors] * Glen Fernandes [endsimplesect] [section Overview] The header `` provides the class and function templates to simplify allocator use. It provides the same functionality as the C++ standard library `std::allocator_traits` but with individual templates for each allocator feature. It also adds additional functionality for allocator aware exception safe construction and destruction of arrays. These facilities also simplify existing libraries by avoiding having to check for `BOOST_NO_CXX11_ALLOCATOR` and conditionally use `std::allocator_traits`. [endsect] [section Examples] The following example shows these utilities used in the definition of an allocator-aware container class: ``` template > class container : boost::empty_value::type> { public: typedef T value_type; typedef A allocator_type; typedef typename boost::allocator_size_type::type size_type; typedef typename boost::allocator_difference_type::type difference_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename boost::allocator_pointer::type pointer; typedef typename boost::allocator_const_pointer::type const_pointer; // ... }; ``` In C++11 or above, aliases such as `boost::allocator_pointer_t` can be used instead of `typename boost::allocator_pointer::type`. The following example allocates storage for an array of `n` elements of `T` using an allocator `a` and constructs `T` elements in that storage. If any exception was thrown during construction of an element, the constructed elements are destroyed in reverse order. ``` template auto create(A& a, std::size_t n) { auto p = a.allocate(n); try { boost::allocator_construct_n(a, boost::to_address(p), n); } catch (...) { a.deallocate(p, n); throw; } return p; } ``` [endsect] [section Reference] ``` namespace boost { template struct allocator_value_type; template using allocator_value_type_t = typename allocator_value_type::type; template struct allocator_pointer; template using allocator_pointer_t = typename allocator_pointer::type; template struct allocator_const_pointer; template using allocator_const_pointer_t = typename allocator_const_pointer::type; template struct allocator_void_pointer; template using allocator_void_pointer_t = typename allocator_void_pointer::type; template struct allocator_const_void_pointer; template using allocator_const_void_pointer_t = typename allocator_const_void_pointer::type; template struct allocator_difference_type; template using allocator_difference_type_t = typename allocator_difference_type::type; template struct allocator_size_type; template using allocator_size_type_t = typename allocator_size_type::type; template struct allocator_propagate_on_container_copy_assignment; template using allocator_propagate_on_container_copy_assignment_t = typename allocator_propagate_on_container_copy_assignment::type; template struct allocator_propagate_on_container_move_assignment; template using allocator_propagate_on_container_move_assignment_t = typename allocator_propagate_on_container_move_assignment::type; template struct allocator_propagate_on_container_swap; template using allocator_propagate_on_container_swap_t = typename allocator_propagate_on_container_swap::type; template struct allocator_is_always_equal; template using allocator_is_always_equal_t = typename allocator_is_always_equal::type; template struct allocator_rebind; template using allocator_rebind_t = typename allocator_rebind::type; template allocator_pointer_t allocator_allocate(A& a, allocator_size_type_t n); template allocator_pointer_t allocator_allocate(A& a, allocator_size_type_t n, allocator_const_void_pointer_t h); template void allocator_deallocate(A& a, allocator_pointer_t p, allocator_size_type_t n); template void allocator_construct(A& a, T* p, Args&&... args); template void allocator_construct_n(A& a, T* p, std::size_t n); template void allocator_construct_n(A& a, T* p, std::size_t n, const T* l, std::size_t m); template void allocator_construct_n(A& a, T* p, std::size_t n, I begin); template void allocator_destroy(A& a, T* p); template void allocator_destroy_n(A& a, T* p, std::size_t n); template allocator_size_type_t allocator_max_size(const A& a); template A allocator_select_on_container_copy_construction(const A& a); } // boost ``` [section Types] [variablelist [[`template struct allocator_value_type;`] [The member `type` is `A::value_type`.]] [[`template struct allocator_pointer;`] [The member `type` is `A::pointer` if valid, otherwise `allocator_value_type_t*`.]] [[`template struct allocator_const_pointer;`] [The member `type` is `A::const_pointer` if valid, otherwise `pointer_traits >::rebind >`.]] [[`template struct allocator_void_pointer;`] [The member `type` is `A::void_pointer` if valid, otherwise `pointer_traits >::rebind`.]] [[`template struct allocator_const_void_pointer;`] [The member `type` is `A::const_void_pointer` if valid, otherwise `pointer_traits >::rebind`.]] [[`template struct allocator_difference_type;`] [The member `type` is `A::difference_type` if valid, otherwise `pointer_traits >::difference_type`.]] [[`template struct allocator_size_type;`] [The member `type` is `A::size_type` if valid, otherwise `std::make_unsigned_t >`.]] [[`template struct allocator_propagate_on_container_copy_assignment;`] [The member `type` is `A::propagate_on_container_copy_assignment` if valid, otherwise `std::false_type`.]] [[`template struct allocator_propagate_on_container_move_assignment;`] [The member `type` is `A::propagate_on_container_move_assignment` if valid, otherwise `std::false_type`.]] [[`template struct allocator_propagate_on_container_swap;`] [The member `type` is `A::propagate_on_container_swap` if valid, otherwise `std::false_type`.]] [[`template struct allocator_is_always_equal;`] [The member `type` is `A::is_always_equal` if valid, otherwise `std::is_empty::type`.]] [[`template struct allocator_rebind;`] [The member `type` is `A::rebind::other` if valid, otherwise `A` if this `A` is `A`.]]] [endsect] [section Functions] [variablelist [[`template allocator_pointer_t allocator_allocate(A& a, allocator_size_type_t n);`] [Calls `a.allocate(n)`.]] [[`template allocator_pointer_t allocator_allocate(A& a, allocator_size_type_t n, allocator_const_void_pointer_t hint);`] [Calls `a.allocate(n, hint)` if valid, otherwise calls `a.allocate(n)`.]] [[`template void allocator_deallocate(A& a, allocator_pointer_t p, allocator_size_type_t n);`] [Calls `a.deallocate(p, n)`.]] [[`template void allocator_construct(A& a, T*p, Args&&... args);`] [Calls `a.construct(p, std::forward(args)...)` if valid, otherwise calls `::new(static_cast(p)) T(std::forward(args)...)`.]] [[`template void alloc_construct_n(A& a, T* p, std::size_t n);`] [Constructs each `i`-th element in order by calling `boost::allocator_construct(a, &p[i])`. If an exception is thrown destroys each already constructed `j`-th element in reverse order by calling `boost::allocator_destroy(a, &p[j])`.]] [[`template void alloc_construct_n(A& a, T* p, std::size_t n, const T* l, std::size_t m);`] [Constructs each `i`-th element in order by calling `boost::allocator_construct(a, &p[i], l[i % m])`. If an exception is thrown destroys each already constructed `j`-th element in reverse order by calling `boost::allocator_destroy(a, &p[j])`.]] [[`template void alloc_construct_n(A& a, T* p, std::size_t n, I begin);`] [Constructs each `i`-th element in order by calling `boost::allocator_construct(a, &p[i], *begin++)`. If an exception is thrown destroys each already constructed `j`-th element in reverse order by calling `boost::allocator_destroy(a, &p[j])`.]] [[`template void allocator_destroy(A& a, T* p);`] [Calls `a.destroy(p)` if valid, otherwise calls `p->~T()`.]] [[`template void allocator_destroy_n(A& a, T* p, std::size_t n);`] [Destroys each `i`-th element in reverse order by calling `boost::allocator_destroy(a, &p[i])`.]] [[`template allocator_size_type_t allocator_max_size(const A& a);`] [Returns `a.max_size()` if valid, otherwise returns `std::numeric_limits >::max() / sizeof(allocator_value_type_t)`.]] [[`template A allocator_select_on_container_copy_construction(const A& a);`] [Returns `a.select_on_container_copy_construction()` if valid, otherwise returns `a`.]]] [endsect] [endsect] [section Acknowledgements] Glen Fernandes implemented the allocator access utilities. [endsect] [endsect]