Files
klubhaus-doorbell/libraries/FastLED/src/fl/unique_ptr.h
2026-02-12 00:45:31 -08:00

256 lines
7.1 KiB
C++

#pragma once
#include "fl/namespace.h"
#include "fl/type_traits.h"
#include "fl/utility.h" // for fl::move, fl::forward, fl::swap
#include "fl/stdint.h" // for fl::size_t
#include "fl/cstddef.h" // for fl::nullptr_t
#include "fl/initializer_list.h" // for consistency (though not used in unique_ptr itself)
namespace fl {
template<typename T>
struct default_delete {
void operator()(T* ptr) const {
delete ptr;
}
// Allow conversion from derived to base type deleters
template<typename U>
default_delete(const default_delete<U>&) noexcept {}
default_delete() = default;
};
template<typename T>
struct default_delete<T[]> {
void operator()(T* ptr) const {
delete[] ptr;
}
};
template<typename T, typename Deleter = default_delete<T>>
class unique_ptr {
public:
using element_type = T;
using deleter_type = Deleter;
using pointer = T*;
private:
pointer ptr_;
Deleter deleter_;
public:
// Constructors
constexpr unique_ptr() noexcept : ptr_(nullptr), deleter_() {}
constexpr unique_ptr(fl::nullptr_t) noexcept : ptr_(nullptr), deleter_() {}
explicit unique_ptr(pointer p) noexcept : ptr_(p), deleter_() {}
unique_ptr(pointer p, const Deleter& d) noexcept : ptr_(p), deleter_(d) {}
unique_ptr(pointer p, Deleter&& d) noexcept : ptr_(p), deleter_(fl::move(d)) {}
// Move constructor
unique_ptr(unique_ptr&& u) noexcept : ptr_(u.release()), deleter_(fl::move(u.deleter_)) {}
// Converting move constructor
template<typename U, typename E>
unique_ptr(unique_ptr<U, E>&& u) noexcept
: ptr_(u.release()), deleter_(fl::move(u.get_deleter())) {}
// Copy semantics deleted
unique_ptr(const unique_ptr&) = delete;
unique_ptr& operator=(const unique_ptr&) = delete;
// Move assignment
unique_ptr& operator=(unique_ptr&& u) noexcept {
if (this != &u) {
reset(u.release());
deleter_ = fl::move(u.deleter_);
}
return *this;
}
// Converting move assignment
template<typename U, typename E>
unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept {
reset(u.release());
deleter_ = fl::move(u.get_deleter());
return *this;
}
// nullptr assignment
unique_ptr& operator=(fl::nullptr_t) noexcept {
reset();
return *this;
}
// Destructor
~unique_ptr() {
if (ptr_) {
deleter_(ptr_);
}
}
// Observers
pointer get() const noexcept { return ptr_; }
Deleter& get_deleter() noexcept { return deleter_; }
const Deleter& get_deleter() const noexcept { return deleter_; }
explicit operator bool() const noexcept { return ptr_ != nullptr; }
// Access
T& operator*() const { return *ptr_; }
pointer operator->() const noexcept { return ptr_; }
// Modifiers
pointer release() noexcept {
pointer tmp = ptr_;
ptr_ = nullptr;
return tmp;
}
void reset(pointer p = nullptr) noexcept {
pointer old_ptr = ptr_;
ptr_ = p;
if (old_ptr) {
deleter_(old_ptr);
}
}
void swap(unique_ptr& u) noexcept {
using fl::swap;
swap(ptr_, u.ptr_);
swap(deleter_, u.deleter_);
}
};
// Array specialization for scoped_array consolidation
template<typename T, typename Deleter>
class unique_ptr<T[], Deleter> {
public:
using element_type = T;
using deleter_type = Deleter;
using pointer = T*;
private:
pointer ptr_;
Deleter deleter_;
public:
// Constructors
constexpr unique_ptr() noexcept : ptr_(nullptr), deleter_() {}
constexpr unique_ptr(fl::nullptr_t) noexcept : ptr_(nullptr), deleter_() {}
explicit unique_ptr(pointer p) noexcept : ptr_(p), deleter_() {}
unique_ptr(pointer p, const Deleter& d) noexcept : ptr_(p), deleter_(d) {}
unique_ptr(pointer p, Deleter&& d) noexcept : ptr_(p), deleter_(fl::move(d)) {}
// Move constructor
unique_ptr(unique_ptr&& u) noexcept : ptr_(u.release()), deleter_(fl::move(u.deleter_)) {}
// Converting move constructor
template<typename U, typename E>
unique_ptr(unique_ptr<U, E>&& u) noexcept
: ptr_(u.release()), deleter_(fl::move(u.get_deleter())) {}
// Copy semantics deleted
unique_ptr(const unique_ptr&) = delete;
unique_ptr& operator=(const unique_ptr&) = delete;
// Move assignment
unique_ptr& operator=(unique_ptr&& u) noexcept {
if (this != &u) {
reset(u.release());
deleter_ = fl::move(u.deleter_);
}
return *this;
}
// Converting move assignment
template<typename U, typename E>
unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept {
reset(u.release());
deleter_ = fl::move(u.get_deleter());
return *this;
}
// nullptr assignment
unique_ptr& operator=(fl::nullptr_t) noexcept {
reset();
return *this;
}
// Destructor
~unique_ptr() {
if (ptr_) {
deleter_(ptr_);
}
}
// Observers
pointer get() const noexcept { return ptr_; }
Deleter& get_deleter() noexcept { return deleter_; }
const Deleter& get_deleter() const noexcept { return deleter_; }
explicit operator bool() const noexcept { return ptr_ != nullptr; }
// Array access (replaces scoped_array functionality)
T& operator[](fl::size_t i) const { return ptr_[i]; }
// Modifiers
pointer release() noexcept {
pointer tmp = ptr_;
ptr_ = nullptr;
return tmp;
}
void reset(pointer p = nullptr) noexcept {
pointer old_ptr = ptr_;
ptr_ = p;
if (old_ptr) {
deleter_(old_ptr);
}
}
void swap(unique_ptr& u) noexcept {
using fl::swap;
swap(ptr_, u.ptr_);
swap(deleter_, u.deleter_);
}
};
// Non-member functions using FL equivalents
template<typename T, typename Deleter>
void swap(unique_ptr<T, Deleter>& lhs, unique_ptr<T, Deleter>& rhs) noexcept {
lhs.swap(rhs);
}
// Comparison operators using FL equivalents
template<typename T1, typename Deleter1, typename T2, typename Deleter2>
bool operator==(const unique_ptr<T1, Deleter1>& lhs, const unique_ptr<T2, Deleter2>& rhs) {
return lhs.get() == rhs.get();
}
template<typename T1, typename Deleter1, typename T2, typename Deleter2>
bool operator!=(const unique_ptr<T1, Deleter1>& lhs, const unique_ptr<T2, Deleter2>& rhs) {
return !(lhs == rhs);
}
template<typename T, typename Deleter>
bool operator==(const unique_ptr<T, Deleter>& ptr, fl::nullptr_t) noexcept {
return !ptr;
}
template<typename T, typename Deleter>
bool operator==(fl::nullptr_t, const unique_ptr<T, Deleter>& ptr) noexcept {
return !ptr;
}
template<typename T, typename Deleter>
bool operator!=(const unique_ptr<T, Deleter>& ptr, fl::nullptr_t) noexcept {
return static_cast<bool>(ptr);
}
template<typename T, typename Deleter>
bool operator!=(fl::nullptr_t, const unique_ptr<T, Deleter>& ptr) noexcept {
return static_cast<bool>(ptr);
}
} // namespace fl