Advertisement
anechka_ne_plach

Untitled

Oct 10th, 2021
184
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.30 KB | None | 0 0
  1. #include <memory>
  2. #include <cstddef>
  3. #include <iostream>
  4. #include <string>
  5.  
  6. #include <type_traits>
  7. #include <utility>
  8.  
  9. #include <cassert>
  10. #include <type_traits>
  11.  
  12. class MyInt {
  13. public:
  14.     static int AliveCount() {
  15.         return count_alive;
  16.     }
  17.  
  18.     MyInt() {
  19.         ++count_alive;
  20.     }
  21.  
  22.     MyInt(int value) : value_(value) {
  23.         ++count_alive;
  24.     };
  25.  
  26.     MyInt(const MyInt& other) : value_(other.value_) {
  27.         ++count_alive;
  28.     }
  29.  
  30.     MyInt(MyInt&&) = delete;
  31.  
  32.     MyInt& operator=(const MyInt& other) {
  33.         value_ = other.value_;
  34.         ++count_alive;
  35.         return *this;
  36.     }
  37.  
  38.     MyInt& operator=(MyInt&& other) = delete;
  39.  
  40.     ~MyInt() {
  41.         --count_alive;
  42.     }
  43.  
  44.     bool operator==(int other) const {
  45.         return value_ == other;
  46.     }
  47.  
  48. private:
  49.     int value_;
  50.  
  51.     inline static int count_alive = 0;
  52. };
  53.  
  54. template <class T>
  55. class Deleter {
  56. public:
  57.     Deleter() = default;
  58.  
  59.     Deleter(int tag) : tag_(tag) {
  60.     }
  61.  
  62.     Deleter(const Deleter&) = delete;
  63.  
  64.     Deleter(Deleter&& rhs) noexcept : tag_(rhs.tag_) {
  65.         rhs.tag_ = 0;
  66.     }
  67.  
  68.     Deleter& operator=(const Deleter&) = delete;
  69.  
  70.     Deleter& operator=(Deleter&& r) noexcept {
  71.         tag_ = r.tag_;
  72.         r.tag_ = 0;
  73.         return *this;
  74.     }
  75.  
  76.     ~Deleter() = default;
  77.  
  78.     int GetTag() const {
  79.         return tag_;
  80.     }
  81.  
  82.     void operator()(T* p) const {
  83.         static_assert(sizeof(T) > 0);
  84.         static_assert(!std::is_void<T>::value);
  85.         delete p;
  86.     }
  87.  
  88.     bool IsConst() const {
  89.         return true;
  90.     }
  91.  
  92.     bool IsConst() {
  93.         return false;
  94.     }
  95.  
  96. private:
  97.     int tag_ = 0;
  98. };
  99.  
  100. template <class T>
  101. class Deleter<T[]> {
  102. public:
  103.     Deleter() = default;
  104.  
  105.     Deleter(int tag) : tag_(tag) {
  106.     }
  107.  
  108.     Deleter(const Deleter&) = delete;
  109.  
  110.     Deleter(Deleter&& rhs) noexcept : tag_(rhs.tag_) {
  111.         rhs.tag_ = 0;
  112.     }
  113.  
  114.     Deleter& operator=(const Deleter&) = delete;
  115.  
  116.     Deleter& operator=(Deleter&& r) noexcept {
  117.         tag_ = r.tag_;
  118.         r.tag_ = 0;
  119.         return *this;
  120.     }
  121.  
  122.     ~Deleter() = default;
  123.  
  124.     int GetTag() const {
  125.         return tag_;
  126.     }
  127.  
  128.     void operator()(T* p) const {
  129.         static_assert(sizeof(T) > 0);
  130.         static_assert(!std::is_void<T>::value);
  131.         delete[] p;
  132.     }
  133.  
  134.     bool IsConst() const {
  135.         return true;
  136.     }
  137.  
  138.     bool IsConst() {
  139.         return false;
  140.     }
  141.  
  142. private:
  143.     int tag_ = 0;
  144. };
  145.  
  146. template <typename T>
  147. class CopyableDeleter {
  148. public:
  149.     CopyableDeleter() = default;
  150.  
  151.     CopyableDeleter(int tag) : tag_(tag) {
  152.     }
  153.  
  154.     CopyableDeleter(const CopyableDeleter&) = default;
  155.  
  156.     CopyableDeleter(CopyableDeleter&& rhs) noexcept : tag_(rhs.tag_) {
  157.         rhs.tag_ = 0;
  158.     }
  159.  
  160.     CopyableDeleter& operator=(const CopyableDeleter&) = default;
  161.  
  162.     CopyableDeleter& operator=(CopyableDeleter&& r) noexcept {
  163.         tag_ = r.tag_;
  164.         r.tag_ = 0;
  165.         return *this;
  166.     }
  167.  
  168.     ~CopyableDeleter() = default;
  169.  
  170.     int GetTag() const {
  171.         return tag_;
  172.     }
  173.  
  174.     void operator()(T* p) const {
  175.         static_assert(sizeof(T) > 0);
  176.         static_assert(!std::is_void<T>::value);
  177.         delete p;
  178.     }
  179.  
  180.     bool IsConst() const {
  181.         return true;
  182.     }
  183.  
  184.     bool IsConst() {
  185.         return false;
  186.     }
  187.  
  188. private:
  189.     int tag_ = 0;
  190. };
  191.  
  192. struct VoidPtrDeleter {
  193.     void operator()(void* ptr) {
  194.         free(ptr);
  195.     }
  196. };
  197.  
  198. template <typename T>
  199. void DeleteFunction(T* ptr) {
  200.     delete ptr;
  201. }
  202.  
  203. template <typename T>
  204. struct StatefulDeleter {
  205.     int some_useless_field = 0;
  206.  
  207.     void operator()(T* ptr) {
  208.         delete ptr;
  209.         ++some_useless_field;
  210.     }
  211. };
  212.  
  213. template <typename T, std::size_t I, bool = std::is_empty_v<T> && !std::is_final_v<T>>
  214. struct CompressedPairElement {
  215. public:
  216.     CompressedPairElement() {
  217.     }
  218.     template <typename Tp>
  219.     CompressedPairElement(Tp&& other) : value_(std::forward<decltype(other)>(other)) {
  220.     }
  221.  
  222.     template <typename Tp>
  223.     CompressedPairElement& operator=(Tp&& other) {
  224.         value_ = std::forward<decltype(other)>(other);
  225.     }
  226.  
  227.     const T& Get() const {
  228.         return value_;
  229.     }
  230.     T& Get() {
  231.         return value_;
  232.     }
  233.  
  234. private:
  235.     T value_{};
  236. };
  237.  
  238. template <typename T, std::size_t I>
  239. struct CompressedPairElement<T, I, true> : public T {
  240. public:
  241.     CompressedPairElement() {
  242.     }
  243.     template <typename Tp>
  244.     CompressedPairElement(Tp&& other) {
  245.     }
  246.     const T& Get() const {
  247.         return *this;
  248.     }
  249.     T& Get() {
  250.         return *this;
  251.     }
  252. };
  253.  
  254. template <typename F, typename S>
  255. class CompressedPair : protected CompressedPairElement<F, 0>,
  256.                        protected CompressedPairElement<S, 1> {
  257.     using First = CompressedPairElement<F, 0>;
  258.     using Second = CompressedPairElement<S, 1>;
  259.  
  260. public:
  261.     CompressedPair() {
  262.     }
  263.     template <typename U, typename V>
  264.     CompressedPair(U&& first, V&& second)
  265.             : First(std::forward<decltype(first)>(first)),
  266.               Second(std::forward<decltype(second)>(second)) {
  267.     }
  268.     F& GetFirst() {
  269.         return First::Get();
  270.     }
  271.     S& GetSecond() {
  272.         return Second::Get();
  273.     }
  274.     const F& GetFirst() const {
  275.         return First::Get();
  276.     }
  277.     const S& GetSecond() const {
  278.         return Second::Get();
  279.     }
  280. };
  281.  
  282. int counter = 0;
  283.  
  284.  // Primary template
  285. template <typename T, typename Deleter = std::default_delete<T>>
  286. class UniquePtr {
  287. public:
  288.    
  289.     // Constructors
  290.  
  291.     explicit UniquePtr(T* ptr = nullptr) {
  292.          ++counter;
  293.          id = std::to_string(counter);
  294.          std::cerr << id << " constructor from pointer" << std::endl;
  295.         uptr_ = CompressedPair<T*, Deleter>(ptr, Deleter());
  296.     }
  297.  
  298.     template<typename Del>
  299.     UniquePtr(T *ptr, Del&& deleter) : uptr_(CompressedPair<T*, Deleter>(ptr, std::forward<decltype(deleter)>(deleter))){
  300.          ++counter;
  301.          id = std::to_string(counter);
  302.          std::cerr << id << " constructor from pointer with deleter" << std::endl;
  303.     }
  304.  
  305.     UniquePtr(const UniquePtr& other) = delete;
  306.  
  307.     UniquePtr(UniquePtr&& other) noexcept {
  308.          ++counter;
  309.          id = std::to_string(counter);
  310.          std::cerr << id << " move constructor from " << other.id << std::endl;
  311.         if (uptr_.GetFirst() != other.uptr_.GetFirst()) {
  312.             std::swap(uptr_, other.uptr_);
  313.             other.uptr_.GetFirst() = nullptr;
  314.         }
  315.     }
  316.     template <typename Tp>
  317.     UniquePtr(UniquePtr<Tp>&& other) noexcept : uptr_(other.uptr_.GetFirst(), std::forward<decltype(other.uptr_.GetSecond())>(other.uptr_.GetSecond())) {
  318.          ++counter;
  319.          id = std::to_string(counter);
  320.          other.uptr_.GetFirst() = nullptr;
  321.          std::cerr << id << " derived move constructor from " << other.id << std::endl;
  322.     }
  323.  
  324.    
  325.     // `operator=`-s
  326.  
  327.     UniquePtr& operator=(const UniquePtr& other) = delete;
  328.  
  329.     UniquePtr& operator=(UniquePtr&& other) noexcept {
  330.          std::cerr << id << " = " << other.id << std::endl;
  331.         if (uptr_.GetFirst() != other.uptr_.GetFirst()) {
  332.             std::swap(uptr_.GetFirst(), other.uptr_.GetFirst());
  333.             uptr_.GetSecond() = std::forward<Deleter>(other.uptr_.GetSecond());
  334.             other.uptr_.GetSecond()(other.uptr_.GetFirst());
  335.             other.uptr_.GetFirst() = nullptr;
  336.         }
  337.         return *this;
  338.     }
  339.  
  340.     UniquePtr& operator=(std::nullptr_t) {
  341.          std::cerr << id << " = nullptr" << std::endl;
  342.         uptr_.GetSecond()(uptr_.GetFirst());
  343.         uptr_ = CompressedPair<T*, Deleter>(nullptr, Deleter());
  344.         return *this;
  345.     }
  346.  
  347.    
  348.     // Destructor
  349.  
  350.     ~UniquePtr() {
  351.          std::cerr << id << " deleted" << std::endl;
  352.         uptr_.GetSecond()(uptr_.GetFirst());
  353.     }
  354.  
  355.    
  356.      //Modifiers
  357.  
  358.     T* Release() noexcept {
  359.          std::cerr << "released " << id << std::endl;
  360.         T* tmp = uptr_.GetFirst();
  361.         uptr_.GetFirst() = nullptr;
  362.         return tmp;
  363.     }
  364.  
  365.     void Reset(T* ptr = nullptr) noexcept {
  366.          std::cerr << "reset " << id << std::endl;
  367.         T* old_ptr = uptr_.GetFirst();
  368.         uptr_.GetFirst() = ptr;
  369.         if (old_ptr) {
  370.             uptr_.GetSecond()(old_ptr);
  371.         }
  372.     }
  373.  
  374.     void Swap(UniquePtr& other) noexcept {
  375.         std::cerr << id << " swapped with " << other.id << std::endl;
  376.         std::swap(uptr_, other.uptr_);
  377.     }
  378.  
  379.    
  380.      //Observers
  381.  
  382.     T* Get() const noexcept {
  383.          std::cerr << "got " << id << std::endl;
  384.         return uptr_.GetFirst();
  385.     }
  386.  
  387.     Deleter& GetDeleter() {
  388.         std::cerr << "got deleter " << id << std::endl;
  389.         return uptr_.GetSecond();
  390.     }
  391.  
  392.     const Deleter& GetDeleter() const {
  393.         std::cerr << "got deleter const " << id << std::endl;
  394.         return uptr_.GetSecond();
  395.     }
  396.  
  397.     explicit operator bool() const {
  398.         std::cerr << "checked if nullptr " << id << std::endl;
  399.         return uptr_.GetFirst() != nullptr;
  400.     }
  401.  
  402.    
  403.     // Single-object dereference operators
  404.  
  405.     typename std::add_lvalue_reference<T>::type
  406.     operator*() const {
  407.         std::cerr << "operator* for " << id << std::endl;
  408.         return *Get();
  409.     }
  410.  
  411.     T* operator->() const {
  412.         std::cerr << "operator -> from " << id << std::endl;
  413.         return uptr_.GetFirst();
  414.     }
  415.  
  416. private:
  417.     CompressedPair<T*, Deleter> uptr_;
  418.     template<class U, class D>
  419.     friend class UniquePtr;
  420.     std::string id = "NULLPOINTER";
  421. };
  422.  
  423. // Specialization for arrays
  424. template <typename T, typename Deleter>
  425. class UniquePtr<T[], Deleter> {
  426. public:
  427.      //Constructors
  428.  
  429.     explicit UniquePtr(T* ptr = nullptr) {
  430.          ++counter;
  431.          id = std::to_string(counter);
  432.          std::cerr << id << " constructor from pointer" << std::endl;
  433.          uptr_ = CompressedPair<T*, Deleter>(ptr, Deleter());
  434.     }
  435.  
  436.     UniquePtr(T *ptr, Deleter deleter) {
  437.          ++counter;
  438.          id = std::to_string(counter);
  439.          std::cerr << id << " constructor from pointer with deleter" << std::endl;;
  440.         uptr_ = CompressedPair<T*, Deleter>(ptr, deleter);
  441.     }
  442.  
  443.     UniquePtr(const UniquePtr& other) = delete;
  444.  
  445.     UniquePtr(UniquePtr&& other) noexcept {
  446.          ++counter;
  447.          id = std::to_string(counter);
  448.          std::cerr << id << " move constructor from " << other.id << std::endl;
  449.         if (uptr_.GetFirst() != other.uptr_.GetFirst()) {
  450.             uptr_ = other.uptr_;
  451.             other.uptr_.GetFirst() = nullptr;
  452.         }
  453.     }
  454.     template <typename Tp>
  455.     UniquePtr(UniquePtr<Tp>&& other) noexcept : uptr_(other.uptr_.GetFirst(), other.uptr_.GetSecond()) {
  456.          ++counter;
  457.          id = std::to_string(counter);
  458.         other.uptr_.GetFirst() = nullptr;
  459.          std::cerr << id << " derived move constructor from " << other.id << std::endl;
  460.     }
  461.  
  462.    
  463.    //  `operator=`-s
  464.  
  465.     UniquePtr& operator=(const UniquePtr& other) = delete;
  466.  
  467.     UniquePtr& operator=(UniquePtr&& other) noexcept {
  468.          std::cerr << id << " = " << other.id << std::endl;
  469.         if (uptr_.GetFirst() != other.uptr_.GetFirst()) {
  470.             std::swap(uptr_, other.uptr_);
  471.             other.uptr_.GetFirst() = nullptr;
  472.         }
  473.         return *this;
  474.     }
  475.  
  476.     UniquePtr& operator=(std::nullptr_t) {
  477.          std::cerr << id << " = nullptr" << std::endl;
  478.         uptr_.GetSecond()(uptr_.GetFirst());
  479.         uptr_ = CompressedPair<T*, Deleter>(nullptr, Deleter());
  480.         return *this;
  481.     }
  482.  
  483.    
  484.    //  Destructor
  485.  
  486.     ~UniquePtr() {
  487.          std::cerr << id << " deleted" << std::endl;
  488.         uptr_.GetSecond()(uptr_.GetFirst());
  489.     }
  490.  
  491.    
  492.     // Modifiers
  493.  
  494.     T* Release() noexcept {
  495.          std::cerr << "released " << id << std::endl;
  496.         T* tmp = uptr_.GetFirst();
  497.         uptr_.GetFirst() = nullptr;
  498.         return tmp;
  499.     }
  500.  
  501.     void Reset(T* ptr = nullptr) noexcept {
  502.          std::cerr << "reset " << id << std::endl;
  503.         T* old_ptr = uptr_.GetFirst();
  504.         uptr_.GetFirst() = ptr;
  505.         if (old_ptr) {
  506.             uptr_.GetSecond()(old_ptr);
  507.         }
  508.     }
  509.  
  510.     void Swap(UniquePtr& other) noexcept {
  511.         std::swap(uptr_, other.uptr_);
  512.     }
  513.  
  514.     T& operator[](size_t i) {
  515.         return Get()[i];
  516.     }
  517.  
  518.    
  519.      //Observers
  520.  
  521.     T* Get() const noexcept {
  522.          std::cerr << "got " << id << std::endl;
  523.         return uptr_.GetFirst();
  524.     }
  525.  
  526.     Deleter& GetDeleter() {
  527.         return uptr_.GetSecond();
  528.     }
  529.  
  530.     const Deleter& GetDeleter() const {
  531.         return uptr_.GetSecond();
  532.     }
  533.  
  534.     explicit operator bool() const {
  535.         return uptr_.GetFirst() != nullptr;
  536.     }
  537.  
  538.     const T& operator[](size_t i) const {
  539.         return Get()[i];
  540.     }
  541.  
  542. private:
  543.     CompressedPair<T*, Deleter> uptr_;
  544.     template<class U, class D>
  545.     friend class UniquePtr;
  546.     std::string id = "NULLPOINTER";
  547. };
  548.  
  549. #include <tuple>
  550.  
  551. int main() {
  552.         {
  553.             const CopyableDeleter<MyInt> cd;
  554.             UniquePtr<MyInt, CopyableDeleter<MyInt>> s(new MyInt, cd);
  555.         }
  556.         {
  557.             Deleter<MyInt> d;
  558.             UniquePtr<MyInt, Deleter<MyInt>> s(new MyInt, std::move(d));
  559.         }
  560.         {
  561.             UniquePtr<MyInt, Deleter<MyInt>> s(new MyInt, Deleter<MyInt>{});
  562.         }
  563.         {
  564.             Deleter<MyInt> d;
  565.             UniquePtr<MyInt, Deleter<MyInt>&> s(new MyInt, d);
  566.         }
  567.         {
  568.             Deleter<MyInt> d;
  569.             UniquePtr<MyInt, const Deleter<MyInt>&> s1(new MyInt, d);
  570.  
  571.             const Deleter<MyInt>& cr = d;
  572.             UniquePtr<MyInt, const Deleter<MyInt>&> s2(new MyInt, cr);
  573.         }
  574.         std::cerr << std::endl;
  575.         {
  576.             MyInt* p1 = new MyInt(1);
  577.             UniquePtr<MyInt, Deleter<MyInt>> s1(p1, Deleter<MyInt>(1));
  578.             MyInt* p2 = new MyInt(2);
  579.             UniquePtr<MyInt, Deleter<MyInt>> s2(p2, Deleter<MyInt>(2));
  580.  
  581.             s1.Swap(s2);
  582.  
  583.             assert(s1.Get() == p2);
  584.             assert(*s1 == 2);
  585.             assert(s2.Get() == p1);
  586.             assert(*s2 == 1);
  587.             assert(s1.GetDeleter().GetTag() == 2);
  588.             assert(s2.GetDeleter().GetTag() == 1);
  589.             assert(MyInt::AliveCount() == 2);
  590.  
  591.             std::swap(s1, s2);
  592.  
  593.             assert(s1.Get() == p1);
  594.             assert(*s1 == 1);
  595.             assert(s2.Get() == p2);
  596.             assert(*s2 == 2);
  597.             assert(s1.GetDeleter().GetTag() == 1);
  598.             assert(s2.GetDeleter().GetTag() == 2);
  599.         }
  600.         {
  601.             UniquePtr<MyInt, Deleter<MyInt>> s1(new MyInt, Deleter<MyInt>(5));
  602.             MyInt* p = s1.Get();
  603.             UniquePtr<MyInt, Deleter<MyInt>> s2(new MyInt);
  604.  
  605.             assert(MyInt::AliveCount() == 2);
  606.             assert(s1.GetDeleter().GetTag() == 5);
  607.             assert(s2.GetDeleter().GetTag() == 0);
  608.  
  609.             s2 = std::move(s1);
  610.  
  611.             assert(s2.Get() == p);
  612.             assert(s1.Get() == nullptr);
  613.             assert(MyInt::AliveCount() == 1);
  614.             assert(s2.GetDeleter().GetTag() == 5);
  615.             assert(s1.GetDeleter().GetTag() == 0);
  616.         }
  617.         {
  618.             CopyableDeleter<MyInt> d1(5);
  619.             UniquePtr<MyInt, CopyableDeleter<MyInt>&> s1(new MyInt, d1);
  620.             MyInt* p1 = s1.Get();
  621.  
  622.             CopyableDeleter<MyInt> d2(6);
  623.             UniquePtr<MyInt, CopyableDeleter<MyInt>&> s2(new MyInt, d2);
  624.  
  625.             assert(MyInt::AliveCount() == 2);
  626.  
  627.             s2 = std::move(s1);
  628.  
  629.             assert(s2.Get() == p1);
  630.             assert(s1.Get() == nullptr);
  631.             assert(MyInt::AliveCount() == 1);
  632.             assert(d1.GetTag() == 5);
  633.             assert(d2.GetTag() == 5);
  634.         }
  635.         {
  636.             UniquePtr<MyInt, Deleter<MyInt>> p;
  637.  
  638.             assert(!p.GetDeleter().IsConst());
  639.         }
  640.         {
  641.             const UniquePtr<MyInt, Deleter<MyInt>> p;
  642.  
  643.             assert(p.GetDeleter().IsConst());
  644.         }
  645.         {
  646.             using UDRef = UniquePtr<MyInt, Deleter<MyInt>&>;
  647.             Deleter<MyInt> d;
  648.  
  649.             UDRef p(nullptr, d);
  650.             const UDRef& cp = p;
  651.  
  652.             assert(!p.GetDeleter().IsConst());
  653.             assert(!cp.GetDeleter().IsConst());
  654.         }
  655.         {
  656.             using UDConstRef = UniquePtr<MyInt, const Deleter<MyInt>&>;
  657.             const Deleter<MyInt> d;
  658.  
  659.             UDConstRef p(nullptr, d);
  660.             const UDConstRef& cp = p;
  661.  
  662.             assert(p.GetDeleter().IsConst());
  663.             assert(cp.GetDeleter().IsConst());
  664.         }
  665.         {
  666.             UniquePtr<void, VoidPtrDeleter> p(malloc(100));
  667.         }
  668.     {
  669.         UniquePtr<MyInt[]> u(new MyInt[100]);
  670.         assert(MyInt::AliveCount() == 100);
  671.         u.Reset();
  672.         assert(MyInt::AliveCount() == 0);
  673.     }
  674.     {
  675.         UniquePtr<MyInt[], Deleter<MyInt[]>> u(new MyInt[100]);
  676.         assert(MyInt::AliveCount() == 100);
  677.         u.Reset();
  678.         assert(MyInt::AliveCount() == 0);
  679.     }
  680.     int* arr = new int[5];
  681.     for (size_t i = 0; i < 5; ++i) {
  682.         arr[i] = i;
  683.     }
  684.  
  685.     UniquePtr<int[]> u(arr);
  686.     for (int i = 0; i < 5; ++i) {
  687.         assert(u[i] == i);
  688.         u[i] = -i;
  689.         assert(u[i] == -i);
  690.     }
  691.     {
  692.         std::cerr << sizeof(UniquePtr<int>) << " " << sizeof(void*) << "\n";
  693. //        static_assert(sizeof(UniquePtr<int>) == sizeof(void*));
  694. //        static_assert(sizeof(UniquePtr<int, std::default_delete<int>>) == sizeof(int*));
  695.     }
  696.     return 0;
  697. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement