跳转至

base/include/base/weak_ptr/weak_ptr.h

Non-owning weak reference for exclusively owned resources. More...

Namespaces

Name
cf

Classes

Name
class cf::WeakPtr
Non-owning weak reference for exclusively owned resources.

Detailed Description

Non-owning weak reference for exclusively owned resources.

Author: N/A

Version: N/A

Since: N/A

Date: N/A

Unlike std::weak_ptr, WeakPtr does not participate in reference counting. The resource is exclusively owned by an owner (typically holding WeakPtrFactory), and WeakPtr acts as a "claim ticket" that becomes invalid when the owner disappears.

Source code

#pragma once

#include "private/weak_ptr_internals.h"

#include <cassert>
#include <type_traits>

namespace cf {

// Forward declaration
template <typename T> class WeakPtrFactory;

template <typename T> class WeakPtr {
  public:
    // ------------------------------------------------------------
    // Construction
    // ------------------------------------------------------------

    constexpr WeakPtr() noexcept = default;

    constexpr WeakPtr(std::nullptr_t) noexcept {}

    WeakPtr(const WeakPtr&) noexcept = default;

    WeakPtr& operator=(const WeakPtr&) noexcept = default;

    WeakPtr(WeakPtr&&) noexcept = default;

    WeakPtr& operator=(WeakPtr&&) noexcept = default;

    template <typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
    WeakPtr(const WeakPtr<U>& other) noexcept : ptr_(other.ptr_), flag_(other.flag_) {}

    template <typename U, typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
    WeakPtr& operator=(const WeakPtr<U>& other) noexcept {
        ptr_ = other.ptr_;
        flag_ = other.flag_;
        return *this;
    }

    ~WeakPtr() = default;

    // ------------------------------------------------------------
    // Access
    // ------------------------------------------------------------

    [[nodiscard]] T* Get() const noexcept {
        if (flag_ && flag_->IsAlive())
            return ptr_;
        return nullptr;
    }

    T* operator->() const noexcept {
        assert(IsValid() && "Dereferencing an invalid WeakPtr");
        return ptr_;
    }

    T& operator*() const noexcept {
        assert(IsValid() && "Dereferencing an invalid WeakPtr");
        return *ptr_;
    }

    // ------------------------------------------------------------
    // State Query
    // ------------------------------------------------------------

    [[nodiscard]] bool IsValid() const noexcept { return Get() != nullptr; }

    explicit operator bool() const noexcept { return IsValid(); }

    // ------------------------------------------------------------
    // Reset
    // ------------------------------------------------------------

    void Reset() noexcept {
        ptr_ = nullptr;
        flag_ = nullptr;
    }

    // ------------------------------------------------------------
    // Comparison
    // ------------------------------------------------------------

    bool operator==(const WeakPtr& other) const noexcept { return Get() == other.Get(); }

    bool operator!=(const WeakPtr& other) const noexcept { return !(*this == other); }

    bool operator==(std::nullptr_t) const noexcept { return !IsValid(); }

    bool operator!=(std::nullptr_t) const noexcept { return IsValid(); }

    // ------------------------------------------------------------
    // Dynamic Cast (Base -> Derived conversion)
    // ------------------------------------------------------------

    template <typename Source> static WeakPtr DynamicCast(const WeakPtr<Source>& other) noexcept {
        if (!other.flag_ || !other.flag_->IsAlive()) {
            return WeakPtr();
        }
        T* casted = dynamic_cast<T*>(other.ptr_);
        if (casted) {
            return WeakPtr(casted, other.flag_);
        }
        return WeakPtr();
    }

  private:
    // Only WeakPtrFactory can construct valid WeakPtr instances

    explicit WeakPtr(T* ptr, internal::WeakReferenceFlagPtr flag) noexcept
        : ptr_(ptr), flag_(std::move(flag)) {}

    T* ptr_ = nullptr;

    internal::WeakReferenceFlagPtr flag_ = nullptr;

    template <typename U> friend class WeakPtr;

    template <typename U> friend class WeakPtrFactory;
};

} // namespace cf

Updated on 2026-03-09 at 10:14:01 +0000