Advertisement
Alexander_Surov

Stalker

Apr 5th, 2024
752
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.35 KB | None | 0 0
  1. #ifndef STALKER
  2. #define STALKER
  3.  
  4. #include <memory>
  5.  
  6. # ifndef STALKER_NAME
  7. # define STALKER_NAME self
  8. # endif
  9.  
  10. // class Example {
  11. //   my::Stalker<Example> self;  // and distribute by self.get()
  12. // };
  13.  
  14. namespace my {
  15.  
  16.   // Note: thread safe -> std::shared_ptr instead of raw pointers
  17.  
  18.   /**
  19.    * @brief `Stalker` allows to track current address of `Owner`
  20.    *
  21.    * @details `Stalker` shares classes `stalker` which provide pointer to the `Owner` via `ref()` or `ptr()`
  22.    *
  23.    * @note `Owner` must have only one instance of `Stalker`, which must be named identically to `STALKER_NAME` definition (defaults to `self`)
  24.    *
  25.    * @tparam Owner  type of class that owns `Stalker`, i.e. the one that needs to be tracked
  26.    *
  27.    * @def if user wants to name `Stalker` member field differently, he should #define STALKER_NAME <name>
  28.    */
  29.   template <typename Owner>
  30.   class Stalker {
  31.  
  32.     struct Hubspot;
  33.     class ImitatorBase;
  34.     class Imitator;
  35.     class ConstImitator;
  36.  
  37.  
  38.    public:
  39.     using value_type = Owner;
  40.  
  41.     using reference = value_type&;
  42.     using const_reference = const value_type&;
  43.  
  44.     using pointer = value_type*;
  45.     using const_pointer = const value_type*;
  46.  
  47.     using stalker_base = ImitatorBase;
  48.     using stalker = Imitator;
  49.     using const_stalker = ConstImitator;
  50.  
  51.  
  52.    private:
  53.     struct Hubspot {
  54.       pointer ptr;
  55.  
  56.      public:
  57.       explicit Hubspot(const pointer& p) noexcept : ptr(p) {
  58.       }
  59.       ~Hubspot() = default;
  60.     };
  61.  
  62.  
  63.     class ImitatorBase {
  64.       friend Stalker;
  65.  
  66.      protected:
  67.       Hubspot* ptr_;
  68.  
  69.      protected:
  70.       explicit ImitatorBase(Hubspot* const& p) noexcept : ptr_(p) {
  71.       }
  72.  
  73.      public:
  74.       ImitatorBase() noexcept : ptr_(nullptr) {
  75.       }
  76.       ~ImitatorBase() = default;
  77.     };
  78.  
  79.  
  80.     class Imitator : ImitatorBase {
  81.       friend ConstImitator;
  82.  
  83.      public:
  84.       using ImitatorBase::ImitatorBase;
  85.  
  86.       Imitator(const ConstImitator&) = delete;
  87.       Imitator(ConstImitator&&) = delete;
  88.  
  89.       Imitator& operator=(const ConstImitator&) = delete;
  90.       Imitator& operator=(ConstImitator&&) = delete;
  91.  
  92.      public:
  93.       reference ref() const noexcept {
  94.         return *ptr();
  95.       }
  96.       pointer ptr() const noexcept {
  97.         return ImitatorBase::ptr_->ptr;
  98.       }
  99.       operator bool() const noexcept {
  100.         return ImitatorBase::ptr_->ptr != nullptr;
  101.       }
  102.     };
  103.  
  104.  
  105.     class ConstImitator : ImitatorBase {
  106.       friend Imitator;
  107.  
  108.      public:
  109.       using ImitatorBase::ImitatorBase;
  110.  
  111.       ConstImitator(const Imitator& other) noexcept : ImitatorBase(other.Imitator::ptr_) {
  112.       }
  113.       ConstImitator(Imitator&& other) noexcept : ImitatorBase(other.Imitator::ptr_) {
  114.       }
  115.  
  116.       ConstImitator& operator=(const Imitator& other) noexcept {
  117.         ImitatorBase::ptr_ = other.Imitator::ptr_;
  118.         return *this;
  119.       }
  120.       ConstImitator& operator=(Imitator&& other) noexcept {
  121.         ImitatorBase::ptr_ = other.Imitator::ptr_;
  122.         return *this;
  123.       }
  124.  
  125.      public:
  126.       const_reference ref() const noexcept {
  127.         return *(ImitatorBase::ptr_->ptr);
  128.       }
  129.       const_pointer ptr() const noexcept {
  130.         return ImitatorBase::ptr_->ptr;
  131.       }
  132.       operator bool() const noexcept {
  133.         return ImitatorBase::ptr_->ptr_ != nullptr;
  134.       }
  135.     };
  136.  
  137.  
  138.    private:
  139.     std::unique_ptr<Hubspot> hub_;
  140.     static constexpr ptrdiff_t shift_ = offsetof(value_type, STALKER_NAME);
  141.  
  142.  
  143.    public:
  144.     Stalker() : hub_(std::make_unique<Hubspot>(ptr())) {
  145.     }
  146.  
  147.     Stalker(const Stalker& other) : hub_(std::make_unique<Hubspot>(ptr())) {
  148.     }
  149.     Stalker(Stalker&& other) noexcept : hub_(std::move(other.hub_)) {
  150.       hub_->ptr = ptr();
  151.     }
  152.  
  153.     Stalker& operator=(const Stalker& other) noexcept {
  154.       return *this;
  155.     }
  156.     Stalker& operator=(Stalker&& other) noexcept {
  157.       if (this != &other) {
  158.         hub_ = std::move(other.hub_);
  159.         hub_->ptr = ptr();
  160.       }
  161.       return *this;
  162.     }
  163.  
  164.     ~Stalker() = default;
  165.  
  166.  
  167.    private:
  168.     pointer ptr() const noexcept {
  169.       return reinterpret_cast<pointer>(reinterpret_cast<char*>(const_cast<Stalker*>(this)) - shift_);
  170.     }
  171.  
  172.  
  173.    public:
  174.     stalker get() noexcept {
  175.       return Imitator(hub_.get());
  176.     }
  177.     const_stalker get() const noexcept {
  178.       return ConstImitator(hub_.get());
  179.     }
  180.   };
  181.  
  182. }
  183.  
  184. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement