Add allocator_traits that uses allocator_access

This commit is contained in:
Glen Fernandes
2021-12-02 23:39:47 -05:00
parent 74c770206a
commit c8b989d80b
6 changed files with 350 additions and 0 deletions

116
doc/allocator_traits.qbk Normal file
View File

@ -0,0 +1,116 @@
[/
Copyright 2021 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_traits allocator_traits]
[simplesect Authors]
* Glen Fernandes
[endsimplesect]
[section Overview]
This header <boost/core/allocator_traits.hpp> provides an implementation of the
C++ standard library class template `allocator_traits` based on the facilities
in [link core.allocator_access Allocator Access]. Users should still prefer the
individual traits, but this utility exists to simplify migration.
[endsect]
[section Reference]
```
namespace boost {
template<class A>
struct allocator_traits {
using allocator_type = A;
using value_type = allocator_value_type_t<A>;
using pointer = allocator_pointer_t<A>;
using const_pointer = allocator_const_pointer_t<A>;
using void_pointer = allocator_void_pointer_t<A>;
using const_pointer = allocator_const_void_pointer_t<A>;
using difference_type = allocator_difference_type_t<A>;
using size_type = allocator_size_type_t<A>;
using propagate_on_container_copy_assignment =
allocator_propagate_on_container_copy_assignment_t<A>;
using propagate_on_container_move_assignment =
allocator_propagate_on_container_move_assignment_t<A>;
using propagate_on_container_swap =
allocator_propagate_on_container_swap_t<A>;
using is_always_equal = allocator_is_always_equal_t<A>;
template<class T>
using rebind_traits = allocator_traits<allocator_rebind_t<A, T> >;
static pointer allocate(A& a, size_type n);
static pointer allocate(A& a, size_type n, const_void_pointer h);
static void deallocate(A& a, pointer p, size_type n);
template<class T, class... Args>
static void construct(A& a, T* p, Args&&... args);
static void destroy(A& a, T* p);
static size_type max_size(const A& a) noexcept;
static A select_on_container_copy_construction(const A& a);
};
} /* boost */
```
[section Static member functions]
[variablelist
[[`static pointer allocate(A& a, size_type n);`]
[Equivalent to: `return boost::allocator_allocate(a, n);`]]
[[`static pointer allocate(A& a, size_type n, const_void_pointer h);`]
[Equivalent to: `return boost::allocator_allocate(a, n, h);`]]
[[`static void deallocate(A& a, pointer p, size_type n);`]
[Equivalent to: `return boost::allocator_deallocate(a, n, h);`]]
[[`template<class T, class... Args>
static void construct(A& a, T* p, Args&&... args);`]
[Equivalent to:
`return boost::allocator_construct(a, p, std::forward<Args>(args)...);`]]
[[`static void destroy(A& a, T* p);`]
[Equivalent to: `return boost::allocator_destroy(a, p);`]]
[[`static size_type max_size(const A& a);`]
[Equivalent to: `return boost::allocator_max_size(a);`]]
[[`static A select_on_container_copy_construction(const A& a);`]
[Equivalent to:
`return boost::allocator_select_on_container_copy_construction(a);`]]]
[endsect]
[section Notes]
# The member `rebind_alloc` is not provided for parity with C++03 where it is
unimplementable. Instead of `allocator_traits<A>::rebind_alloc<U>` you can
express the same with `allocator_traits<A>::rebind_traits<U>::allocator_type`
or more simply with `allocator_rebind_t<A, T>`.
[endsect]
[endsect]
[endsect]

View File

@ -6,6 +6,12 @@
[section Revision History]
[section Changes in 1.79.0]
* Added `boost::allocator_traits`, an implementation of `std::allocator_traits`.
[endsect]
[section Changes in 1.78.0]
* Added a generic implementation to `boost/core/cmath.hpp`, enabled when `BOOST_CORE_USE_GENERIC_CMATH`

View File

@ -42,6 +42,7 @@ criteria for inclusion is that the utility component be:
[include addressof.qbk]
[include allocator_access.qbk]
[include allocator_traits.qbk]
[include alloc_construct.qbk]
[include bit.qbk]
[include checked_delete.qbk]

View File

@ -0,0 +1,112 @@
/*
Copyright 2021 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_CORE_ALLOCATOR_TRAITS_HPP
#define BOOST_CORE_ALLOCATOR_TRAITS_HPP
#include <boost/core/allocator_access.hpp>
namespace boost {
template<class A>
struct allocator_traits {
typedef A allocator_type;
typedef typename allocator_value_type<A>::type value_type;
typedef typename allocator_pointer<A>::type pointer;
typedef typename allocator_const_pointer<A>::type const_pointer;
typedef typename allocator_void_pointer<A>::type void_pointer;
typedef typename allocator_const_void_pointer<A>::type const_void_pointer;
typedef typename allocator_difference_type<A>::type difference_type;
typedef typename allocator_size_type<A>::type size_type;
typedef typename allocator_propagate_on_container_copy_assignment<A>::type
propagate_on_container_copy_assignment;
typedef typename allocator_propagate_on_container_move_assignment<A>::type
propagate_on_container_move_assignment;
typedef typename allocator_propagate_on_container_swap<A>::type
propagate_on_container_swap;
typedef typename allocator_is_always_equal<A>::type is_always_equal;
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template<class T>
using rebind_traits = allocator_traits<typename
allocator_rebind<A, T>::type>;
#else
template<class T>
struct rebind_traits
: allocator_traits<typename allocator_rebind<A, T>::type> { };
#endif
static pointer allocate(A& a, size_type n) {
return boost::allocator_allocate(a, n);
}
static pointer allocate(A& a, size_type n, const_void_pointer h) {
return boost::allocator_allocate(a, n, h);
}
static void deallocate(A& a, pointer p, size_type n) {
return boost::allocator_deallocate(a, p, n);
}
template<class T>
static void construct(A& a, T* p) {
boost::allocator_construct(a, p);
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class T, class V, class... Args>
static void construct(A& a, T* p, V&& v, Args&&... args) {
boost::allocator_construct(a, p, std::forward<V>(v),
std::forward<Args>(args)...);
}
#else
template<class T, class V>
static void construct(A& a, T* p, V&& v) {
boost::allocator_construct(a, p, std::forward<V>(v));
}
#endif
#else
template<class T, class V>
static void construct(A& a, T* p, const V& v) {
boost::allocator_construct(a, p, v);
}
template<class T, class V>
static void construct(A& a, T* p, V& v) {
boost::allocator_construct(a, p, v);
}
#endif
template<class T>
static void destroy(A& a, T* p) {
boost::allocator_destroy(a, p);
}
static size_type max_size(const A& a) BOOST_NOEXCEPT {
return boost::allocator_max_size(a);
}
static A select_on_container_copy_construction(const A& a) {
return boost::allocator_select_on_container_copy_construction(a);
}
};
} /* boost */
#endif

View File

@ -236,6 +236,7 @@ run allocator_allocate_hint_test.cpp ;
run allocator_deallocate_test.cpp ;
run allocator_max_size_test.cpp ;
run allocator_soccc_test.cpp ;
run allocator_traits_test.cpp ;
lib lib_typeid : lib_typeid.cpp : <link>shared:<define>LIB_TYPEID_DYN_LINK=1 ;

View File

@ -0,0 +1,114 @@
/*
Copyright 2021 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/core/allocator_traits.hpp>
#include <boost/core/lightweight_test_trait.hpp>
template<class T>
class creator {
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef void* void_pointer;
typedef const void* const_void_pointer;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
template<class U>
struct rebind {
typedef creator<U> other;
};
explicit creator(int value) BOOST_NOEXCEPT
: state_(value) { }
template<class U>
creator(const creator<U>& other) BOOST_NOEXCEPT
: state_(other.state) { }
std::size_t max_size() const BOOST_NOEXCEPT {
return static_cast<std::size_t>(-1) / sizeof(T);
}
T* allocate(std::size_t n, const void* = 0) {
return static_cast<T*>(::operator new(sizeof(T) * n));
}
void deallocate(T* p, std::size_t) {
::operator delete(p);
}
int state() const {
return state_;
}
private:
int state_;
};
template<class T, class U>
inline bool operator==(const creator<T>& lhs,
const creator<U>& rhs) BOOST_NOEXCEPT
{
return lhs.state() == rhs.state();
}
template<class T, class U>
inline bool operator!=(const creator<T>& lhs,
const creator<U>& rhs) BOOST_NOEXCEPT
{
return !(lhs == rhs);
}
int main()
{
BOOST_TEST_TRAIT_SAME(creator<int>,
boost::allocator_traits<creator<int> >::allocator_type);
BOOST_TEST_TRAIT_SAME(int,
boost::allocator_traits<creator<int> >::value_type);
BOOST_TEST_TRAIT_SAME(int*,
boost::allocator_traits<creator<int> >::pointer);
BOOST_TEST_TRAIT_SAME(const int*,
boost::allocator_traits<creator<int> >::const_pointer);
BOOST_TEST_TRAIT_SAME(void*,
boost::allocator_traits<creator<int> >::void_pointer);
BOOST_TEST_TRAIT_SAME(const void*,
boost::allocator_traits<creator<int> >::const_void_pointer);
BOOST_TEST_TRAIT_SAME(std::ptrdiff_t,
boost::allocator_traits<creator<int> >::difference_type);
BOOST_TEST_TRAIT_SAME(std::size_t,
boost::allocator_traits<creator<int> >::size_type);
BOOST_TEST_TRAIT_FALSE((boost::allocator_traits<creator<int> >::
propagate_on_container_copy_assignment));
BOOST_TEST_TRAIT_FALSE((boost::allocator_traits<creator<int> >::
propagate_on_container_move_assignment));
BOOST_TEST_TRAIT_FALSE((boost::allocator_traits<creator<int> >::
propagate_on_container_swap));
BOOST_TEST_TRAIT_FALSE((boost::allocator_traits<creator<int> >::
is_always_equal));
BOOST_TEST_TRAIT_SAME(creator<char>,
boost::allocator_traits<creator<int> >::
rebind_traits<char>::allocator_type);
creator<int> a(1);
int* p1 = boost::allocator_traits<creator<int> >::allocate(a, 1);
if (BOOST_TEST(p1)) {
int* p2 = boost::allocator_traits<creator<int> >::allocate(a, 1, p1);
if (BOOST_TEST(p2)) {
boost::allocator_traits<creator<int> >::deallocate(a, p2, 1);
}
boost::allocator_traits<creator<int> >::construct(a, p1, 5);
BOOST_TEST_EQ(*p1, 5);
boost::allocator_traits<creator<int> >::destroy(a, p1);
boost::allocator_traits<creator<int> >::deallocate(a, p1, 1);
}
BOOST_TEST_EQ(boost::allocator_traits<creator<int> >::max_size(a),
static_cast<std::size_t>(-1) / sizeof(int));
BOOST_TEST(boost::allocator_traits<creator<int> >::
select_on_container_copy_construction(a) == a);
return boost::report_errors();
}