mirror of
https://github.com/boostorg/core.git
synced 2025-07-30 12:57:26 +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 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`
|
||||
|
@ -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]
|
||||
|
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_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 ;
|
||||
|
||||
|
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