107 struct control_block {
108 using allocator_traits = std::allocator_traits<A>;
109 typename allocator_traits::pointer p_;
111 virtual ~control_block() =
default;
112 virtual void destroy(A& alloc) = 0;
113 virtual control_block* clone(
const A& alloc) = 0;
114 virtual control_block* move(
const A& alloc) = 0;
118 class direct_control_block final :
public control_block {
119 union uninitialized_storage {
122 uninitialized_storage() {}
124 ~uninitialized_storage() {}
127 using cb_allocator =
typename std::allocator_traits<
128 A>::template rebind_alloc<direct_control_block<U>>;
129 using cb_alloc_traits = std::allocator_traits<cb_allocator>;
132 template <
class... Ts>
133 direct_control_block(
const A& alloc, Ts&&... ts) {
134 cb_allocator cb_alloc(alloc);
135 cb_alloc_traits::construct(cb_alloc, std::addressof(storage_.u_),
136 std::forward<Ts>(ts)...);
137 control_block::p_ = std::addressof(storage_.u_);
140 control_block* clone(
const A& alloc)
override {
141 cb_allocator cb_alloc(alloc);
142 auto mem = cb_alloc_traits::allocate(cb_alloc, 1);
144 cb_alloc_traits::construct(cb_alloc, mem, alloc, storage_.u_);
147 cb_alloc_traits::deallocate(cb_alloc, mem, 1);
152 control_block* move(
const A& alloc)
override {
153 cb_allocator cb_alloc(alloc);
154 auto mem = cb_alloc_traits::allocate(cb_alloc, 1);
156 cb_alloc_traits::construct(cb_alloc, mem, alloc,
157 std::move(storage_.u_));
160 cb_alloc_traits::deallocate(cb_alloc, mem, 1);
165 void destroy(A& alloc)
override {
166 cb_allocator cb_alloc(alloc);
167 cb_alloc_traits::destroy(cb_alloc, std::addressof(storage_.u_));
168 cb_alloc_traits::deallocate(cb_alloc,
this, 1);
173 using allocator_traits = std::allocator_traits<A>;
174 using alloc_base = detail::empty_base_optimization<A>;
176 template <
class U,
class... Ts>
177 control_block* create_control_block(Ts&&... ts)
const {
178 using cb_allocator =
typename std::allocator_traits<
179 A>::template rebind_alloc<direct_control_block<U>>;
181 using cb_alloc_traits = std::allocator_traits<cb_allocator>;
182 auto mem = cb_alloc_traits::allocate(cb_alloc, 1);
185 std::forward<Ts>(ts)...);
188 cb_alloc_traits::deallocate(cb_alloc, mem, 1);
196 using pointer =
typename allocator_traits::pointer;
199 template <
typename TT = T,
200 typename std::enable_if<std::is_default_constructible<TT>::value,
202 polymorphic(std::allocator_arg_t,
const A& alloc) : alloc_base(alloc) {
203 cb_ = create_control_block<T>();
206 template <
typename TT = T,
207 typename std::enable_if<std::is_default_constructible<TT>::value,
210 typename std::enable_if<std::is_default_constructible<AA>::value,
213 cb_ = create_control_block<T>();
217 class U,
class... Ts,
218 typename std::enable_if<std::is_constructible<U, Ts&&...>::value,
220 typename std::enable_if<std::is_copy_constructible<U>::value,
int>::type =
222 typename std::enable_if<std::is_base_of<T, U>::value,
int>::type = 0>
225 : alloc_base(alloc) {
226 cb_ = create_control_block<U>(std::forward<Ts>(ts)...);
230 class U,
class I,
class... Ts,
231 typename std::enable_if<
232 std::is_constructible<U, std::initializer_list<I>, Ts&&...>::value,
234 typename std::enable_if<std::is_copy_constructible<U>::value,
int>::type =
236 typename std::enable_if<std::is_base_of<T, U>::value,
int>::type = 0>
238 std::initializer_list<I> ilist, Ts&&... ts)
239 : alloc_base(alloc) {
240 cb_ = create_control_block<T>(ilist, std::forward<Ts>(ts)...);
244 class U,
class I,
class... Ts,
245 typename std::enable_if<
246 std::is_constructible<U, std::initializer_list<I>, Ts&&...>::value,
248 typename std::enable_if<std::is_copy_constructible<U>::value,
int>::type =
250 typename std::enable_if<std::is_base_of<T, U>::value,
int>::type = 0,
252 typename std::enable_if<std::is_default_constructible<AA>::value,
257 std::forward<Ts>(ts)...) {}
260 class U,
class... Ts,
261 typename std::enable_if<std::is_constructible<U, Ts&&...>::value,
263 typename std::enable_if<std::is_copy_constructible<U>::value,
int>::type =
265 typename std::enable_if<std::is_base_of<T, U>::value,
int>::type = 0,
267 typename std::enable_if<std::is_default_constructible<AA>::value,
271 std::forward<Ts>(ts)...) {}
275 typename std::enable_if<
277 typename std::remove_cv<
typename std::remove_reference<
278 U>::type>::type>::value,
280 typename std::enable_if<
281 std::is_copy_constructible<
typename std::remove_cv<
282 typename std::remove_reference<U>::type>::type>::value,
284 typename std::enable_if<
286 T,
typename std::remove_cv<
287 typename std::remove_reference<U>::type>::type>::value,
292 typename std::remove_reference<U>::type>::type>{},
293 std::forward<U>(u)) {}
297 typename std::enable_if<
299 typename std::remove_cv<
typename std::remove_reference<
300 U>::type>::type>::value,
302 typename std::enable_if<
303 std::is_copy_constructible<
typename std::remove_cv<
304 typename std::remove_reference<U>::type>::type>::value,
306 typename std::enable_if<
308 T,
typename std::remove_cv<
309 typename std::remove_reference<U>::type>::type>::value,
314 typename std::remove_reference<U>::type>::type>{},
315 std::forward<U>(u)) {}
318 : alloc_base(alloc) {
320 cb_ = other.cb_->clone(alloc_base::get());
328 allocator_traits::select_on_container_copy_construction(
333 std::allocator_arg_t,
const A& alloc,
334 polymorphic&& other)
noexcept(allocator_traits::is_always_equal::value)
335 : alloc_base(alloc) {
336 if (allocator_traits::propagate_on_container_copy_assignment::value) {
344 if (!other.valueless_after_move()) {
354 :
polymorphic(std::allocator_arg, other.get_allocator(),
360 if (
this == &other)
return *
this;
366 allocator_traits::propagate_on_container_copy_assignment::value;
373 auto tmp = other.cb_->clone(update_alloc ? other.alloc_base::get()
385 allocator_traits::propagate_on_container_move_assignment::value ||
386 allocator_traits::is_always_equal::value) {
387 if (
this == &other)
return *
this;
393 allocator_traits::propagate_on_container_move_assignment::value;
395 if (other.valueless_after_move()) {
399 std::swap(cb_, other.cb_);
404 auto tmp = other.cb_->move(update_alloc ? other.alloc_base::get()
438 return cb_ ==
nullptr;
444 std::allocator_traits<A>::propagate_on_container_swap::value ||
445 std::allocator_traits<A>::is_always_equal::value) {
446 if (allocator_traits::propagate_on_container_swap::value) {
449 std::swap(cb_, other.cb_);
453 std::swap(cb_, other.cb_);
461 polymorphic& rhs)
noexcept(
noexcept(lhs.swap(rhs))) {
466 void reset() noexcept {
467 if (cb_ !=
nullptr) {