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