-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathebo_allocator.h
154 lines (116 loc) · 5.43 KB
/
ebo_allocator.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#ifndef COOL_EBO_ALLOCATOR_H_
#define COOL_EBO_ALLOCATOR_H_
#include <cool/ebo_wrapper.h>
#include <memory>
#include <type_traits>
#include <utility>
///////////////////////////////////////////////////////////////////////////////
// ebo_allocator
//
// ebo_allocator is an allocator (meets the C++17 allocator requirements)
// which wraps another allocator.
//
// The intended use is to inherit from ebo_allocator<A> and call
// inner_allocator() to get a reference to the held allocator.
//
// Assignment, copy construction, etc. are already implemented based on the
// POC?A typedefs.
//
///////////////////////////////////////////////////////////////////////////////
namespace cool
{
template<typename A>
class ebo_allocator : private ebo_wrapper<A>
{
using wrapper = ebo_wrapper<A>;
using traits = std::allocator_traits<A>;
public:
using inner_allocator_type = A;
using value_type = typename A::value_type;
using pointer = typename traits::pointer;
using const_pointer = typename traits::const_pointer;
using void_pointer = typename traits::void_pointer;
using const_void_pointer = typename traits::const_void_pointer;
using size_type = typename traits::size_type;
using difference_type = typename traits::difference_type;
using propagate_on_container_copy_assignment = typename traits::propagate_on_container_copy_assignment;
using propagate_on_container_move_assignment = typename traits::propagate_on_container_move_assignment;
using propagate_on_container_swap = typename traits::propagate_on_container_swap;
using is_always_equal = typename traits::is_always_equal;
inner_allocator_type & inner_allocator() noexcept
{ return wrapper::ref(); }
inner_allocator_type const& inner_allocator() const noexcept
{ return wrapper::ref(); }
template<typename U>
struct rebind { using other = ebo_allocator<typename traits::template rebind_alloc<U>>; };
// Constructors
constexpr ebo_allocator() = default;
template<typename U>
constexpr ebo_allocator(ebo_allocator<U> const& that) noexcept
: wrapper(that.inner_allocator())
{}
template<typename U>
constexpr ebo_allocator(ebo_allocator<U>&& that) noexcept
: wrapper(std::move(that.inner_allocator()))
{}
ebo_allocator(ebo_allocator const& that) noexcept
: wrapper(traits::select_on_container_copy_construction(that.inner_allocator()))
{}
template<typename... Us, typename = std::enable_if_t<std::is_constructible_v<A, Us...>>>
constexpr ebo_allocator(Us&&... us)
noexcept(noexcept(A(std::forward<Us>(us)...)))
: wrapper(std::forward<Us>(us)...)
{}
constexpr ebo_allocator& operator=(ebo_allocator const& that) noexcept
{
if constexpr(propagate_on_container_copy_assignment{})
inner_allocator() = that.inner_allocator();
return *this;
}
constexpr ebo_allocator& operator=(ebo_allocator&& that) noexcept
{
if constexpr(propagate_on_container_move_assignment{})
inner_allocator() = std::move(that.inner_allocator());
return *this;
}
constexpr friend void swap(ebo_allocator& l, ebo_allocator& r) noexcept
{
if constexpr(propagate_on_container_swap{})
{
using std::swap;
swap(l.inner_allocator(), r.inner_allocator());
}
}
pointer allocate(size_type n)
{ return traits::allocate(inner_allocator(), n); }
pointer allocate(size_type n, const_void_pointer y)
{ return traits::allocate(inner_allocator(), n, y); }
void deallocate(pointer p, size_type n)
{ traits::deallocate(inner_allocator(), p, n); }
size_type max_size() const noexcept
{ return traits::max_size(inner_allocator()); }
template<typename... Args>
void construct(value_type* c, Args&&... args)
{ traits::construct(inner_allocator(), c, std::forward<Args>(args)...); }
void destroy(value_type* c)
{ traits::destroy(inner_allocator(), c); }
ebo_allocator select_on_container_copy_construction() const
{ return ebo_allocator(traits::select_on_container_copy_construction(inner_allocator())); }
constexpr friend bool operator==(ebo_allocator const& l, ebo_allocator const& r) noexcept
{
if constexpr(!is_always_equal{})
return l.inner_allocator() == r.inner_allocator();
else
return true;
}
constexpr friend bool operator!=(ebo_allocator const& l, ebo_allocator const& r) noexcept
{ return !(l == r); }
};
template<typename L, typename R>
constexpr bool operator==(ebo_allocator<L> const& l, ebo_allocator<R> const& r) noexcept
{ return l.inner_allocator() == r.inner_allocator(); }
template<typename L, typename R>
constexpr bool operator!=(ebo_allocator<L> const& l, ebo_allocator<R> const& r) noexcept
{ return !(l == r); }
} // cool namespace
#endif /* COOL_EBO_ALLOCATOR_H_ */