mirror of
https://github.com/boostorg/core.git
synced 2025-07-31 13:27:29 +02:00
Add allocator_traits that uses allocator_access
This commit is contained in:
116
doc/allocator_traits.qbk
Normal file
116
doc/allocator_traits.qbk
Normal 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]
|
@ -6,6 +6,12 @@
|
|||||||
|
|
||||||
[section Revision History]
|
[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]
|
[section Changes in 1.78.0]
|
||||||
|
|
||||||
* Added a generic implementation to `boost/core/cmath.hpp`, enabled when `BOOST_CORE_USE_GENERIC_CMATH`
|
* Added a generic implementation to `boost/core/cmath.hpp`, enabled when `BOOST_CORE_USE_GENERIC_CMATH`
|
||||||
|
@ -42,6 +42,7 @@ criteria for inclusion is that the utility component be:
|
|||||||
|
|
||||||
[include addressof.qbk]
|
[include addressof.qbk]
|
||||||
[include allocator_access.qbk]
|
[include allocator_access.qbk]
|
||||||
|
[include allocator_traits.qbk]
|
||||||
[include alloc_construct.qbk]
|
[include alloc_construct.qbk]
|
||||||
[include bit.qbk]
|
[include bit.qbk]
|
||||||
[include checked_delete.qbk]
|
[include checked_delete.qbk]
|
||||||
|
112
include/boost/core/allocator_traits.hpp
Normal file
112
include/boost/core/allocator_traits.hpp
Normal 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
|
@ -236,6 +236,7 @@ run allocator_allocate_hint_test.cpp ;
|
|||||||
run allocator_deallocate_test.cpp ;
|
run allocator_deallocate_test.cpp ;
|
||||||
run allocator_max_size_test.cpp ;
|
run allocator_max_size_test.cpp ;
|
||||||
run allocator_soccc_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 ;
|
lib lib_typeid : lib_typeid.cpp : <link>shared:<define>LIB_TYPEID_DYN_LINK=1 ;
|
||||||
|
|
||||||
|
114
test/allocator_traits_test.cpp
Normal file
114
test/allocator_traits_test.cpp
Normal 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();
|
||||||
|
}
|
Reference in New Issue
Block a user