Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifndef STALKER
- #define STALKER
- #include <memory>
- # ifndef STALKER_NAME
- # define STALKER_NAME self
- # endif
- // class Example {
- // my::Stalker<Example> self; // and distribute by self.get()
- // };
- namespace my {
- // Note: thread safe -> std::shared_ptr instead of raw pointers
- /**
- * @brief `Stalker` allows to track current address of `Owner`
- *
- * @details `Stalker` shares classes `stalker` which provide pointer to the `Owner` via `ref()` or `ptr()`
- *
- * @note `Owner` must have only one instance of `Stalker`, which must be named identically to `STALKER_NAME` definition (defaults to `self`)
- *
- * @tparam Owner type of class that owns `Stalker`, i.e. the one that needs to be tracked
- *
- * @def if user wants to name `Stalker` member field differently, he should #define STALKER_NAME <name>
- */
- template <typename Owner>
- class Stalker {
- struct Hubspot;
- class ImitatorBase;
- class Imitator;
- class ConstImitator;
- public:
- using value_type = Owner;
- using reference = value_type&;
- using const_reference = const value_type&;
- using pointer = value_type*;
- using const_pointer = const value_type*;
- using stalker_base = ImitatorBase;
- using stalker = Imitator;
- using const_stalker = ConstImitator;
- private:
- struct Hubspot {
- pointer ptr;
- public:
- explicit Hubspot(const pointer& p) noexcept : ptr(p) {
- }
- ~Hubspot() = default;
- };
- class ImitatorBase {
- friend Stalker;
- protected:
- Hubspot* ptr_;
- protected:
- explicit ImitatorBase(Hubspot* const& p) noexcept : ptr_(p) {
- }
- public:
- ImitatorBase() noexcept : ptr_(nullptr) {
- }
- ~ImitatorBase() = default;
- };
- class Imitator : ImitatorBase {
- friend ConstImitator;
- public:
- using ImitatorBase::ImitatorBase;
- Imitator(const ConstImitator&) = delete;
- Imitator(ConstImitator&&) = delete;
- Imitator& operator=(const ConstImitator&) = delete;
- Imitator& operator=(ConstImitator&&) = delete;
- public:
- reference ref() const noexcept {
- return *ptr();
- }
- pointer ptr() const noexcept {
- return ImitatorBase::ptr_->ptr;
- }
- operator bool() const noexcept {
- return ImitatorBase::ptr_->ptr != nullptr;
- }
- };
- class ConstImitator : ImitatorBase {
- friend Imitator;
- public:
- using ImitatorBase::ImitatorBase;
- ConstImitator(const Imitator& other) noexcept : ImitatorBase(other.Imitator::ptr_) {
- }
- ConstImitator(Imitator&& other) noexcept : ImitatorBase(other.Imitator::ptr_) {
- }
- ConstImitator& operator=(const Imitator& other) noexcept {
- ImitatorBase::ptr_ = other.Imitator::ptr_;
- return *this;
- }
- ConstImitator& operator=(Imitator&& other) noexcept {
- ImitatorBase::ptr_ = other.Imitator::ptr_;
- return *this;
- }
- public:
- const_reference ref() const noexcept {
- return *(ImitatorBase::ptr_->ptr);
- }
- const_pointer ptr() const noexcept {
- return ImitatorBase::ptr_->ptr;
- }
- operator bool() const noexcept {
- return ImitatorBase::ptr_->ptr_ != nullptr;
- }
- };
- private:
- std::unique_ptr<Hubspot> hub_;
- static constexpr ptrdiff_t shift_ = offsetof(value_type, STALKER_NAME);
- public:
- Stalker() : hub_(std::make_unique<Hubspot>(ptr())) {
- }
- Stalker(const Stalker& other) : hub_(std::make_unique<Hubspot>(ptr())) {
- }
- Stalker(Stalker&& other) noexcept : hub_(std::move(other.hub_)) {
- hub_->ptr = ptr();
- }
- Stalker& operator=(const Stalker& other) noexcept {
- return *this;
- }
- Stalker& operator=(Stalker&& other) noexcept {
- if (this != &other) {
- hub_ = std::move(other.hub_);
- hub_->ptr = ptr();
- }
- return *this;
- }
- ~Stalker() = default;
- private:
- pointer ptr() const noexcept {
- return reinterpret_cast<pointer>(reinterpret_cast<char*>(const_cast<Stalker*>(this)) - shift_);
- }
- public:
- stalker get() noexcept {
- return Imitator(hub_.get());
- }
- const_stalker get() const noexcept {
- return ConstImitator(hub_.get());
- }
- };
- }
- #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement