11 #ifndef ROOT_TADOPTALLOCATOR
12 #define ROOT_TADOPTALLOCATOR
51 class RAdoptAllocator {
53 friend class RAdoptAllocator<bool>;
55 using propagate_on_container_move_assignment = std::true_type;
56 using propagate_on_container_swap = std::true_type;
57 using StdAlloc_t = std::allocator<T>;
58 using value_type =
typename StdAlloc_t::value_type;
59 using pointer =
typename StdAlloc_t::pointer;
60 using const_pointer =
typename StdAlloc_t::const_pointer;
61 using reference =
typename StdAlloc_t::reference;
62 using const_reference =
typename StdAlloc_t::const_reference;
63 using size_type =
typename StdAlloc_t::size_type;
64 using difference_type =
typename StdAlloc_t::difference_type;
67 using other = RAdoptAllocator<U>;
71 enum class EAllocType : char { kOwning, kAdopting, kAdoptingNoAllocYet };
72 using StdAllocTraits_t = std::allocator_traits<StdAlloc_t>;
73 pointer fInitialAddress =
nullptr;
74 EAllocType fAllocType = EAllocType::kOwning;
75 StdAlloc_t fStdAllocator;
79 RAdoptAllocator(pointer p) : fInitialAddress(p), fAllocType(EAllocType::kAdoptingNoAllocYet){};
80 RAdoptAllocator() =
default;
81 RAdoptAllocator(
const RAdoptAllocator &) =
default;
82 RAdoptAllocator(RAdoptAllocator &&) =
default;
83 RAdoptAllocator &operator=(
const RAdoptAllocator &) =
default;
84 RAdoptAllocator &operator=(RAdoptAllocator &&) =
default;
85 RAdoptAllocator(
const RAdoptAllocator<bool> &);
93 template <
class U,
class... Args>
94 void construct(U *p, Args &&... args)
97 if (EAllocType::kAdopting == fAllocType)
99 fStdAllocator.construct(p, args...);
105 pointer allocate(std::size_t n)
107 if (n > std::size_t(-1) /
sizeof(T))
108 throw std::bad_alloc();
109 if (EAllocType::kAdoptingNoAllocYet == fAllocType) {
110 fAllocType = EAllocType::kAdopting;
111 return fInitialAddress;
113 fAllocType = EAllocType::kOwning;
114 return StdAllocTraits_t::allocate(fStdAllocator, n);
118 void deallocate(pointer p, std::size_t n)
120 if (p != fInitialAddress)
121 StdAllocTraits_t::deallocate(fStdAllocator, p, n);
127 if (EAllocType::kAdopting != fAllocType) {
128 fStdAllocator.destroy(p);
132 bool operator==(
const RAdoptAllocator<T> &other)
134 return fInitialAddress == other.fInitialAddress && fAllocType == other.fAllocType &&
135 fStdAllocator == other.fStdAllocator;
138 bool operator!=(
const RAdoptAllocator<T> &other) {
return !(*
this == other); }
140 size_type max_size()
const {
return fStdAllocator.max_size(); };
150 class RAdoptAllocator<bool> {
151 std::allocator<bool> fStdAllocator;
154 template <
typename U>
156 using other = RAdoptAllocator<U>;
159 template <
typename T>
160 friend class RAdoptAllocator;
162 using StdAlloc_t = std::allocator<bool>;
163 using value_type =
typename StdAlloc_t::value_type;
164 using pointer =
typename StdAlloc_t::pointer;
165 using const_pointer =
typename StdAlloc_t::const_pointer;
166 using reference =
typename StdAlloc_t::reference;
167 using const_reference =
typename StdAlloc_t::const_reference;
168 using size_type =
typename StdAlloc_t::size_type;
169 using difference_type =
typename StdAlloc_t::difference_type;
171 RAdoptAllocator() =
default;
172 RAdoptAllocator(
const RAdoptAllocator &) =
default;
174 template <
typename U>
175 RAdoptAllocator(
const RAdoptAllocator<U> &o) : fStdAllocator(o.fStdAllocator)
177 if (o.fAllocType != RAdoptAllocator<U>::EAllocType::kOwning)
178 throw std::runtime_error(
"Cannot rebind owning RAdoptAllocator");
181 bool *allocate(std::size_t n) {
return fStdAllocator.allocate(n); }
183 template <
typename U,
class... Args>
184 void construct(U *p, Args &&... args)
186 fStdAllocator.construct(p, std::forward<Args>(args)...);
189 void deallocate(
bool *p, std::size_t s) noexcept { fStdAllocator.deallocate(p, s); }
194 fStdAllocator.destroy(p);
197 bool operator==(
const RAdoptAllocator &) {
return true; }
199 bool operator!=(
const RAdoptAllocator &) {
return false; }
202 template <
typename T>
203 RAdoptAllocator<T>::RAdoptAllocator(
const RAdoptAllocator<bool> &o) : fStdAllocator(o.fStdAllocator) {}