6 #ifndef XENIUM_DETAIL_DELETABLE_OBJECT_HPP
7 #define XENIUM_DETAIL_DELETABLE_OBJECT_HPP
10 #include <type_traits>
14 #pragma warning(disable : 26495) // uninitialized member variable
17 namespace xenium::reclamation::detail {
19 struct deletable_object {
20 virtual void delete_self() = 0;
21 deletable_object* next =
nullptr;
24 virtual ~deletable_object() =
default;
27 inline void delete_objects(deletable_object*& list) {
29 for (deletable_object* next =
nullptr; cur !=
nullptr; cur = next) {
36 template <
class Derived,
class DeleterT,
class Base>
37 struct deletable_object_with_non_empty_deleter : Base {
38 using Deleter = DeleterT;
39 void delete_self()
override {
40 auto& my_deleter =
reinterpret_cast<Deleter&
>(_deleter_buffer);
41 Deleter deleter(std::move(my_deleter));
42 my_deleter.~Deleter();
44 deleter(
static_cast<Derived*
>(
this));
47 void set_deleter(Deleter deleter) {
new (&_deleter_buffer) Deleter(std::move(deleter)); }
50 using buffer =
typename std::aligned_storage<
sizeof(Deleter),
alignof(Deleter)>::type;
51 buffer _deleter_buffer;
54 template <
class Derived,
class DeleterT,
class Base>
55 struct deletable_object_with_empty_deleter : Base {
56 using Deleter = DeleterT;
57 void delete_self()
override {
58 static_assert(std::is_default_constructible<Deleter>::value,
"empty deleters must be default constructible");
60 deleter(
static_cast<Derived*
>(
this));
63 void set_deleter(Deleter ) {}
66 template <
class Derived,
class Deleter = std::default_delete<Derived>,
class Base = deletable_
object>
67 using deletable_object_impl = std::conditional_t<std::is_empty<Deleter>::value,
68 deletable_object_with_empty_deleter<Derived, Deleter, Base>,
69 deletable_object_with_non_empty_deleter<Derived, Deleter, Base>>;