mirror of
https://github.com/boostorg/core.git
synced 2025-07-29 20:37:22 +02:00
Implement default_allocator
This commit is contained in:
@ -40,6 +40,7 @@ criteria for inclusion is that the utility component be:
|
||||
|
||||
[include addressof.qbk]
|
||||
[include checked_delete.qbk]
|
||||
[include default_allocator.qbk]
|
||||
[include demangle.qbk]
|
||||
[include empty_value.qbk]
|
||||
[include enable_if.qbk]
|
||||
|
113
doc/default_allocator.qbk
Normal file
113
doc/default_allocator.qbk
Normal file
@ -0,0 +1,113 @@
|
||||
[/
|
||||
Copyright 2019 Glen Joseph Fernandes
|
||||
(glenjofe@gmail.com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:default_allocator default_allocator]
|
||||
|
||||
[simplesect Authors]
|
||||
|
||||
* Glen Fernandes
|
||||
|
||||
[endsimplesect]
|
||||
|
||||
[section Overview]
|
||||
|
||||
The header <boost/core/default_allocator.hpp> provides the class template
|
||||
`boost::default_allocator` to serve as a minimal default allocator that:
|
||||
|
||||
* Like C++2a's `std::allocator`, does not provide members such as `construct()`
|
||||
and `destroy()` to be eligible for optimizations by allocator-aware code that
|
||||
detects the absence of these members to provide more optimal construction of
|
||||
objects.
|
||||
* Supports `BOOST_NO_EXCEPTIONS`.
|
||||
* Does not have `std` as an associated namespace.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Reference]
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
template<class T>
|
||||
struct default_allocator {
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef ``['true_type]`` propagate_on_container_move_assignment;
|
||||
typedef ``['true_type]`` is_always_equal;
|
||||
|
||||
template<class U>
|
||||
struct rebind {
|
||||
typedef default_allocator<U> other;
|
||||
};
|
||||
|
||||
constexpr default_allocator() = default;
|
||||
|
||||
template<class U>
|
||||
constexpr default_allocator(const default_allocator<U>&) noexcept { }
|
||||
|
||||
constexpr std::size_t max_size() const noexcept;
|
||||
T* allocate(std::size_t n);
|
||||
void deallocate(T* p, std::size_t);
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
constexpr bool operator==(const default_allocator<T>&,
|
||||
const default_allocator<U>&) noexcept;
|
||||
|
||||
template<class T, class U>
|
||||
constexpr operator!=(const default_allocator<T>&,
|
||||
const default_allocator<U>&) noexcept;
|
||||
|
||||
} /* boost */
|
||||
```
|
||||
|
||||
[section Members]
|
||||
|
||||
[variablelist
|
||||
|
||||
[[`constexpr std::size_t max_size() const noexcept;`]
|
||||
[[variablelist
|
||||
[[Returns][The largest value `N` for which the call `allocate(N)` might
|
||||
succeed.]]]]]
|
||||
[[`T* allocate(std::size_t n);`]
|
||||
[[variablelist
|
||||
[[Returns]
|
||||
[A pointer to the initial element of an array of storage of size
|
||||
`n * sizeof(T)`, aligned appropriately for objects of type `T`.]]
|
||||
[[Remarks][The storage is obtained by calling `::operator new`.]]
|
||||
[[Throws][`std::bad_alloc` if the storage cannot be obtained.]]]]]
|
||||
[[`void deallocate(T* p, std::size_t n);`]
|
||||
[[variablelist
|
||||
[[Requires]
|
||||
[`p` shall be a pointer value obtained from `allocate()`. `n` shall equal the
|
||||
value passed as the first argument to the invocation of `allocate` which
|
||||
returned `p`.]]
|
||||
[[Effects][Deallocates the storage referenced by `p`.]]
|
||||
[[Remarks][Uses `::operator delete`.]]]]]]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Operators]
|
||||
|
||||
[variablelist
|
||||
[[`template<class T, class U> constexpr bool operator==(const
|
||||
default_allocator<T>&, const default_allocator<U>&) noexcept;`]
|
||||
[[variablelist
|
||||
[[Returns][`true`.]]]]]
|
||||
[[`template<class T, class U> constexpr bool operator!=(const
|
||||
default_allocator<T>&, const default_allocator<U>&) noexcept;`]
|
||||
[[variablelist
|
||||
[[Returns][`false`.]]]]]]
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
119
include/boost/core/default_allocator.hpp
Normal file
119
include/boost/core/default_allocator.hpp
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
Copyright 2019 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_DEFAULT_ALLOCATOR_HPP
|
||||
#define BOOST_CORE_DEFAULT_ALLOCATOR_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <new>
|
||||
|
||||
namespace boost {
|
||||
|
||||
#if defined(BOOST_NO_EXCEPTIONS)
|
||||
void throw_exception(const std::exception&);
|
||||
#endif
|
||||
|
||||
namespace default_ {
|
||||
|
||||
struct true_type {
|
||||
typedef bool value_type;
|
||||
typedef true_type type;
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
|
||||
BOOST_CONSTEXPR operator bool() const BOOST_NOEXCEPT {
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR bool operator()() const BOOST_NOEXCEPT {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct default_allocator {
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef true_type propagate_on_container_move_assignment;
|
||||
typedef true_type is_always_equal;
|
||||
|
||||
template<class U>
|
||||
struct rebind {
|
||||
typedef default_allocator<U> other;
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
|
||||
default_allocator() = default;
|
||||
#else
|
||||
BOOST_CONSTEXPR default_allocator() BOOST_NOEXCEPT { }
|
||||
#endif
|
||||
|
||||
template<class U>
|
||||
BOOST_CONSTEXPR default_allocator(const default_allocator<U>&)
|
||||
BOOST_NOEXCEPT { }
|
||||
|
||||
BOOST_CONSTEXPR std::size_t max_size() const BOOST_NOEXCEPT {
|
||||
return ~static_cast<std::size_t>(0) / sizeof(T);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_EXCEPTIONS)
|
||||
T* allocate(std::size_t n) {
|
||||
if (n > max_size()) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
return static_cast<T*>(::operator new(sizeof(T) * n));
|
||||
}
|
||||
|
||||
void deallocate(T* p, std::size_t) {
|
||||
::operator delete(p);
|
||||
}
|
||||
#else
|
||||
T* allocate(std::size_t n) {
|
||||
if (n > max_size()) {
|
||||
boost::throw_exception(std::bad_alloc());
|
||||
}
|
||||
if (!n) {
|
||||
return 0;
|
||||
}
|
||||
void* p = ::operator new(sizeof(T) * n, std::nothrow);
|
||||
if (!p) {
|
||||
boost::throw_exception(std::bad_alloc());
|
||||
}
|
||||
return static_cast<T*>(p);
|
||||
}
|
||||
|
||||
void deallocate(T* p, std::size_t) {
|
||||
::operator delete(p, std::nothrow);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
BOOST_CONSTEXPR inline bool
|
||||
operator==(const default_allocator<T>&,
|
||||
const default_allocator<U>&) BOOST_NOEXCEPT
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
BOOST_CONSTEXPR inline bool
|
||||
operator!=(const default_allocator<T>&,
|
||||
const default_allocator<U>&) BOOST_NOEXCEPT
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
} /* default_ */
|
||||
|
||||
using default_::default_allocator;
|
||||
|
||||
} /* boost */
|
||||
|
||||
#endif
|
@ -136,6 +136,8 @@ run-fail quick_exit_fail.cpp ;
|
||||
|
||||
compile use_default_test.cpp ;
|
||||
|
||||
run default_allocator_test.cpp ;
|
||||
|
||||
lib lib_typeid : lib_typeid.cpp : <link>shared:<define>LIB_TYPEID_DYN_LINK=1 ;
|
||||
|
||||
run test_lib_typeid.cpp lib_typeid : : : <link>shared : test_lib_typeid_shared ;
|
||||
|
211
test/default_allocator_test.cpp
Normal file
211
test/default_allocator_test.cpp
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
Copyright 2019 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/default_allocator.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
|
||||
class type {
|
||||
public:
|
||||
explicit type(int) { }
|
||||
|
||||
private:
|
||||
type(const type&);
|
||||
type& operator=(const type&);
|
||||
};
|
||||
|
||||
void test_value_type()
|
||||
{
|
||||
BOOST_TEST_TRAIT_SAME(int,
|
||||
boost::default_allocator<int>::value_type);
|
||||
BOOST_TEST_TRAIT_SAME(type,
|
||||
boost::default_allocator<type>::value_type);
|
||||
BOOST_TEST_TRAIT_SAME(int[5],
|
||||
boost::default_allocator<int[5]>::value_type);
|
||||
BOOST_TEST_TRAIT_SAME(void,
|
||||
boost::default_allocator<void>::value_type);
|
||||
}
|
||||
|
||||
void test_pointer()
|
||||
{
|
||||
BOOST_TEST_TRAIT_SAME(int*,
|
||||
boost::default_allocator<int>::pointer);
|
||||
BOOST_TEST_TRAIT_SAME(type*,
|
||||
boost::default_allocator<type>::pointer);
|
||||
BOOST_TEST_TRAIT_SAME(int(*)[5],
|
||||
boost::default_allocator<int[5]>::pointer);
|
||||
BOOST_TEST_TRAIT_SAME(void*,
|
||||
boost::default_allocator<void>::pointer);
|
||||
}
|
||||
|
||||
void test_size_type()
|
||||
{
|
||||
BOOST_TEST_TRAIT_SAME(std::size_t,
|
||||
boost::default_allocator<int>::size_type);
|
||||
BOOST_TEST_TRAIT_SAME(std::size_t,
|
||||
boost::default_allocator<type>::size_type);
|
||||
BOOST_TEST_TRAIT_SAME(std::size_t,
|
||||
boost::default_allocator<int[5]>::size_type);
|
||||
BOOST_TEST_TRAIT_SAME(std::size_t,
|
||||
boost::default_allocator<void>::size_type);
|
||||
}
|
||||
|
||||
void test_difference_type()
|
||||
{
|
||||
BOOST_TEST_TRAIT_SAME(std::ptrdiff_t,
|
||||
boost::default_allocator<int>::difference_type);
|
||||
BOOST_TEST_TRAIT_SAME(std::ptrdiff_t,
|
||||
boost::default_allocator<type>::difference_type);
|
||||
BOOST_TEST_TRAIT_SAME(std::ptrdiff_t,
|
||||
boost::default_allocator<int[5]>::difference_type);
|
||||
BOOST_TEST_TRAIT_SAME(std::ptrdiff_t,
|
||||
boost::default_allocator<void>::difference_type);
|
||||
}
|
||||
|
||||
void test_propagate_on_container_move_assignment()
|
||||
{
|
||||
BOOST_TEST_TRAIT_TRUE((boost::default_allocator<int>::
|
||||
propagate_on_container_move_assignment));
|
||||
BOOST_TEST_TRAIT_TRUE((boost::default_allocator<type>::
|
||||
propagate_on_container_move_assignment));
|
||||
BOOST_TEST_TRAIT_TRUE((boost::default_allocator<int[5]>::
|
||||
propagate_on_container_move_assignment));
|
||||
BOOST_TEST_TRAIT_TRUE((boost::default_allocator<void>::
|
||||
propagate_on_container_move_assignment));
|
||||
}
|
||||
|
||||
void test_is_always_equal()
|
||||
{
|
||||
BOOST_TEST_TRAIT_TRUE((boost::default_allocator<int>::is_always_equal));
|
||||
BOOST_TEST_TRAIT_TRUE((boost::default_allocator<type>::is_always_equal));
|
||||
BOOST_TEST_TRAIT_TRUE((boost::default_allocator<int[5]>::is_always_equal));
|
||||
BOOST_TEST_TRAIT_TRUE((boost::default_allocator<void>::is_always_equal));
|
||||
}
|
||||
|
||||
void test_rebind()
|
||||
{
|
||||
BOOST_TEST_TRAIT_SAME(boost::default_allocator<type>,
|
||||
boost::default_allocator<int>::rebind<type>::other);
|
||||
BOOST_TEST_TRAIT_SAME(boost::default_allocator<int[5]>,
|
||||
boost::default_allocator<type>::rebind<int[5]>::other);
|
||||
BOOST_TEST_TRAIT_SAME(boost::default_allocator<void>,
|
||||
boost::default_allocator<int[5]>::rebind<void>::other);
|
||||
BOOST_TEST_TRAIT_SAME(boost::default_allocator<int>,
|
||||
boost::default_allocator<void>::rebind<int>::other);
|
||||
}
|
||||
|
||||
void test_default_construct()
|
||||
{
|
||||
boost::default_allocator<int> a1;
|
||||
(void)a1;
|
||||
boost::default_allocator<type> a2;
|
||||
(void)a2;
|
||||
boost::default_allocator<int[5]> a3;
|
||||
(void)a3;
|
||||
boost::default_allocator<void> a4;
|
||||
(void)a4;
|
||||
}
|
||||
|
||||
void test_copy()
|
||||
{
|
||||
boost::default_allocator<int> a1;
|
||||
boost::default_allocator<int> a2(a1);
|
||||
(void)a2;
|
||||
boost::default_allocator<int[5]> a3;
|
||||
boost::default_allocator<int[5]> a4(a3);
|
||||
(void)a4;
|
||||
boost::default_allocator<void> a5;
|
||||
boost::default_allocator<void> a6(a5);
|
||||
(void)a6;
|
||||
}
|
||||
|
||||
void test_construct_other()
|
||||
{
|
||||
boost::default_allocator<int> a1;
|
||||
boost::default_allocator<type> a2(a1);
|
||||
boost::default_allocator<int[5]> a3(a2);
|
||||
boost::default_allocator<void> a4(a3);
|
||||
boost::default_allocator<int> a5(a4);
|
||||
(void)a5;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::size_t max_size()
|
||||
{
|
||||
return ~static_cast<std::size_t>(0) / sizeof(T);
|
||||
}
|
||||
|
||||
void test_max_size()
|
||||
{
|
||||
BOOST_TEST_EQ(max_size<int>(),
|
||||
boost::default_allocator<int>().max_size());
|
||||
BOOST_TEST_EQ(max_size<type>(),
|
||||
boost::default_allocator<type>().max_size());
|
||||
BOOST_TEST_EQ(max_size<int[5]>(),
|
||||
boost::default_allocator<int[5]>().max_size());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void test_allocate()
|
||||
{
|
||||
boost::default_allocator<T> a;
|
||||
T* p = a.allocate(1);
|
||||
BOOST_TEST(p != 0);
|
||||
a.deallocate(p, 1);
|
||||
p = a.allocate(0);
|
||||
a.deallocate(p, 0);
|
||||
BOOST_TEST_THROWS(a.allocate(a.max_size()), std::bad_alloc);
|
||||
}
|
||||
|
||||
void test_allocate_deallocate()
|
||||
{
|
||||
test_allocate<int>();
|
||||
test_allocate<type>();
|
||||
test_allocate<int[5]>();
|
||||
}
|
||||
|
||||
void test_equals()
|
||||
{
|
||||
BOOST_TEST(boost::default_allocator<int>() ==
|
||||
boost::default_allocator<type>());
|
||||
BOOST_TEST(boost::default_allocator<type>() ==
|
||||
boost::default_allocator<int[5]>());
|
||||
BOOST_TEST(boost::default_allocator<int[5]>() ==
|
||||
boost::default_allocator<void>());
|
||||
BOOST_TEST(boost::default_allocator<void>() ==
|
||||
boost::default_allocator<int>());
|
||||
}
|
||||
|
||||
void test_not_equals()
|
||||
{
|
||||
BOOST_TEST(!(boost::default_allocator<int>() !=
|
||||
boost::default_allocator<type>()));
|
||||
BOOST_TEST(!(boost::default_allocator<type>() !=
|
||||
boost::default_allocator<int[5]>()));
|
||||
BOOST_TEST(!(boost::default_allocator<int[5]>() !=
|
||||
boost::default_allocator<void>()));
|
||||
BOOST_TEST(!(boost::default_allocator<void>() !=
|
||||
boost::default_allocator<int>()));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_value_type();
|
||||
test_pointer();
|
||||
test_size_type();
|
||||
test_difference_type();
|
||||
test_propagate_on_container_move_assignment();
|
||||
test_is_always_equal();
|
||||
test_rebind();
|
||||
test_default_construct();
|
||||
test_copy();
|
||||
test_construct_other();
|
||||
test_max_size();
|
||||
test_allocate_deallocate();
|
||||
test_equals();
|
||||
test_not_equals();
|
||||
return boost::report_errors();
|
||||
}
|
Reference in New Issue
Block a user