General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

191 regels
2.9 KiB

  1. #pragma once
  2. #include "gp/algorithm/modifiers.hpp"
  3. #include "gp/algorithm/move.hpp"
  4. #include "gp/buffer.hpp"
  5. #include "gp/function.hpp"
  6. template<typename T, typename allocator_t = void>
  7. class unique_ptr;
  8. template<typename T>
  9. class unique_ptr<T, void> {
  10. T* ptr;
  11. gp::function<bool(T*)> deallocator;
  12. public:
  13. unique_ptr()
  14. : ptr{nullptr}
  15. {}
  16. template<typename deal>
  17. unique_ptr(T* _ptr, deal func)
  18. : ptr{_ptr}
  19. , deallocator{func}
  20. {}
  21. unique_ptr(unique_ptr&) = delete;
  22. unique_ptr(unique_ptr&& oth)
  23. : ptr{oth.ptr}
  24. , deallocator{oth.deallocator}
  25. {
  26. oth.ptr = nullptr;
  27. }
  28. void operator=(unique_ptr&) = delete;
  29. void operator=(unique_ptr&& oth) {
  30. ptr = oth.ptr;
  31. deallocator = oth.deallocator;
  32. oth.ptr = nullptr;
  33. }
  34. operator bool() {
  35. return ptr != nullptr;
  36. }
  37. T* operator->() {
  38. return ptr;
  39. }
  40. T* operator*() {
  41. return ptr;
  42. }
  43. ~unique_ptr() {
  44. if(ptr) {
  45. ptr->~T();
  46. gp_config::assertion(deallocator(ptr), "freeing unique_ptr failed");
  47. }
  48. }
  49. };
  50. template<typename T, typename allocator>
  51. class unique_ptr<T, gp::reference_wrapper<allocator>>{
  52. T* ptr;
  53. gp::reference_wrapper<allocator> ref;
  54. public:
  55. unique_ptr()
  56. : ptr{nullptr}
  57. {}
  58. template<typename ...Args>
  59. unique_ptr(Args ...args, allocator& _ref)
  60. : ref{_ref} {
  61. auto p = ref.get().allocate(sizeof(T));
  62. if(p)
  63. {
  64. ptr = new(p) T(args...);
  65. } else {
  66. ptr = nullptr;
  67. }
  68. }
  69. unique_ptr(T* _ptr, allocator& _ref)
  70. : ptr{_ptr}
  71. , ref{_ref}
  72. {}
  73. unique_ptr(unique_ptr&) = delete;
  74. unique_ptr(unique_ptr&& oth)
  75. : ptr{oth.ptr}
  76. , ref{oth.ref}
  77. {
  78. oth.ptr = nullptr;
  79. }
  80. void operator=(unique_ptr&) = delete;
  81. void operator=(unique_ptr&& oth) {
  82. ptr = oth.ptr;
  83. ref = oth.ref;
  84. oth.ptr = nullptr;
  85. }
  86. operator bool() {
  87. return ptr != nullptr;
  88. }
  89. T* operator->() {
  90. return ptr;
  91. }
  92. T* operator*() {
  93. return ptr;
  94. }
  95. ~unique_ptr() {
  96. if(ptr) {
  97. ptr->~T();
  98. gp_config::assertion(ref.get().deallocate(ptr), "freeing unique_ptr failed");
  99. }
  100. }
  101. };
  102. template<typename T, typename allocator>
  103. class unique_ptr{
  104. T* ptr;
  105. allocator alloc;
  106. public:
  107. unique_ptr()
  108. : ptr{nullptr}
  109. {}
  110. unique_ptr(T* _ptr, allocator _alloc = allocator{})
  111. : ptr{_ptr}
  112. , alloc{_alloc}
  113. {}
  114. template<typename ...Args>
  115. unique_ptr(Args ...args, allocator _alloc = allocator{})
  116. : alloc{_alloc} {
  117. auto p = alloc.allocate(sizeof(T));
  118. if(p)
  119. {
  120. ptr = new(p) T(args...);
  121. } else {
  122. ptr = nullptr;
  123. }
  124. }
  125. unique_ptr(unique_ptr&) = delete;
  126. unique_ptr(unique_ptr&& oth)
  127. : ptr{oth.ptr}
  128. , alloc{oth.alloc}
  129. {
  130. oth.ptr = nullptr;
  131. }
  132. void operator=(unique_ptr&) = delete;
  133. void operator=(unique_ptr&& oth) {
  134. ptr = oth.ptr;
  135. alloc = oth.alloc;
  136. oth.ptr = nullptr;
  137. }
  138. operator bool() {
  139. return ptr != nullptr;
  140. }
  141. T* operator->() {
  142. return ptr;
  143. }
  144. T* operator*() {
  145. return ptr;
  146. }
  147. ~unique_ptr() {
  148. if(ptr) {
  149. ptr->~T();
  150. gp_config::assertion(alloc.deallocate(ptr), "freeing unique_ptr failed");
  151. }
  152. }
  153. };
  154. class unique_array_ptr {
  155. gp::buffer<char> data;
  156. };