-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdefault_init_allocator.h
109 lines (89 loc) · 3.92 KB
/
default_init_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
#ifndef COOL_DEFAULT_INIT_ALLOCATOR_H_
#define COOL_DEFAULT_INIT_ALLOCATOR_H_
#include <memory>
#include <vector>
#include <cool/ebo_allocator.h>
///////////////////////////////////////////////////////////////////////////////
//
// default_init_allocator<T, A>
//
// An allocator which default initializes (as opposed to value initializes)
// its members when construct(T*) is called.
//
// Template parameters:
// T - the value_type for the allocations
// A - the underlying stateless allocator to call on all other operations
// (defaults to std::allocator<T>)
//
///////////////////////////////////////////////////////////////////////////////
//
// default_init_vector<T, A>
//
// An alias template for std::vector which uses default initialization
// (instead of the typical value initialization) for default constructed
// elements.
//
// Template parameters:
// T - the value_type stored in the vector
// A - the underlying allocator to call on all operations besides default
// construction (defaults to std::allocator<T>)
//
///////////////////////////////////////////////////////////////////////////////
namespace cool
{
template<typename T, typename A = std::allocator<T>>
class default_init_allocator
: private ebo_allocator<A>
{
using ebo_alloc = ebo_allocator<A>;
public:
using typename ebo_alloc::inner_allocator_type;
using ebo_alloc::inner_allocator;
using typename ebo_alloc::pointer;
using typename ebo_alloc::const_pointer;
using typename ebo_alloc::void_pointer;
using typename ebo_alloc::const_void_pointer;
using typename ebo_alloc::value_type;
using typename ebo_alloc::size_type;
using typename ebo_alloc::difference_type;
using typename ebo_alloc::propagate_on_container_copy_assignment;
using typename ebo_alloc::propagate_on_container_move_assignment;
using typename ebo_alloc::propagate_on_container_swap;
using typename ebo_alloc::is_always_equal;
template<typename U>
struct rebind { using other = default_init_allocator<U, typename std::allocator_traits<A>::template rebind_alloc<U>>; };
constexpr default_init_allocator() = default;
template<typename TT, typename AA>
constexpr default_init_allocator(default_init_allocator<TT, AA> const& that) noexcept
: ebo_alloc(that.inner_allocator())
{}
template<typename TT, typename AA>
constexpr default_init_allocator(default_init_allocator<TT, AA>&& that) noexcept
: ebo_alloc(std::move(that.inner_allocator()))
{}
template<typename... Us, typename = std::enable_if_t<std::is_constructible_v<A, Us...>>>
constexpr default_init_allocator(Us&&... us)
noexcept(noexcept(A(std::forward<Us>(us)...)))
: ebo_alloc(std::forward<Us>(us)...)
{}
using ebo_alloc::allocate;
using ebo_alloc::deallocate;
using ebo_alloc::destroy;
using ebo_alloc::max_size;
using ebo_alloc::select_on_container_copy_construction;
void construct(T* p)
{ ::new (static_cast<void*>(p)) T; }
template<typename... Args>
void construct(T* p, Args&&... args)
{ ebo_alloc::construct(p, std::forward<Args>(args)...); }
};
template<typename LT, typename LA, typename RT, typename RA>
constexpr bool operator==(default_init_allocator<LT, LA> const& l, default_init_allocator<RT, RA> const& r) noexcept
{ return l.inner_allocator() == r.inner_allocator(); }
template<typename LT, typename LA, typename RT, typename RA>
constexpr bool operator!=(default_init_allocator<LT, LA> const& l, default_init_allocator<RT, RA> const& r) noexcept
{ return !(l == r); }
template<typename T, typename A = std::allocator<T>>
using default_init_vector = std::vector<T, default_init_allocator<T, A>>;
} // cool namespace
#endif /* COOL_DEFAULT_INIT_ALLOCATOR_H_ */