#pragma once #include "borrowed-ptr.hpp" #include "compat/assert.hpp" #ifdef __GNUG__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" #endif namespace floormat { template template //requires std::is_constructible_v, Ts&&...> bptr::bptr(InPlaceInitT, Ts&&... args) noexcept: bptr{ new std::remove_const_t{ forward(args)... } } {} template bptr::bptr() noexcept: bptr{nullptr} {} template template Y> bptr::bptr(Y* ptr) noexcept: blk{ptr ? new detail_bptr::control_block{const_cast*>(ptr), 1, 1} : nullptr} {} template bptr::~bptr() noexcept { if (blk) detail_bptr::control_block::decrement(blk); } template bptr::bptr(const bptr& other) noexcept: bptr{other, nullptr} {} template bptr::bptr(bptr&& other) noexcept: bptr{move(other), nullptr} {} template bptr& bptr::operator=(const bptr& other) noexcept { return _copy_assign(other); } template bptr& bptr::operator=(bptr&& other) noexcept { return _move_assign(move(other)); } template template Y> bptr::bptr(const bptr& other) noexcept: bptr{other, nullptr} {} template template Y> bptr& bptr::operator=(const bptr& other) noexcept { return _copy_assign(other); } template template Y> bptr::bptr(bptr&& other) noexcept: bptr{move(other), nullptr} {} template template Y> bptr& bptr::operator=(bptr&& other) noexcept { return _move_assign(move(other)); } template void bptr::reset() noexcept { if (blk) detail_bptr::control_block::decrement(blk); } template template Y> void bptr::reset(Y* ptr) noexcept { if (blk) detail_bptr::control_block::decrement(blk); blk = ptr ? new detail_bptr::control_block{const_cast*>(ptr), 1, 1} : nullptr; } template void bptr::destroy() noexcept { if (!blk) return; delete blk->_ptr; blk->_ptr = nullptr; } template bptr& bptr::operator=(std::nullptr_t) noexcept { reset(); return *this; } template template bptr::bptr(const bptr& other, std::nullptr_t) noexcept: blk{other.blk} { if (blk) { ++blk->_soft_count; ++blk->_hard_count; } } template template bptr::bptr(bptr&& other, std::nullptr_t) noexcept: blk{other.blk} { other.blk = nullptr; } template template bptr& bptr::_copy_assign(const bptr& other) noexcept { if (blk != other.blk) { if (blk) detail_bptr::control_block::decrement(blk); blk = other.blk; if (blk) { ++blk->_soft_count; ++blk->_hard_count; } } return *this; } template template bptr& bptr::_move_assign(bptr&& other) noexcept { if (blk) detail_bptr::control_block::decrement(blk); blk = other.blk; other.blk = nullptr; return *this; } template T* bptr::get() const noexcept { if (blk) [[likely]] return static_cast(blk->_ptr); else return nullptr; } template T* bptr::operator->() const noexcept { auto* ret = get(); fm_bptr_assert(ret); return ret; } template T& bptr::operator*() const noexcept { return *operator->(); } template bptr::operator bool() const noexcept { return blk && blk->_ptr; } template bool bptr::operator==(const bptr& other) const noexcept { return blk ? (other.blk && blk->_ptr == other.blk->_ptr) : !other.blk; } template bool bptr::operator==(const bptr& other) const noexcept requires (!std::is_const_v) { return blk ? (other.blk && blk->_ptr == other.blk->_ptr) : !other.blk; } template bool bptr::operator==(const std::nullptr_t&) const noexcept { return !blk || !blk->_ptr; } template std::strong_ordering bptr::operator<=>(const bptr& other) const noexcept { return get() <=> other.get(); } template void bptr::swap(bptr& other) noexcept { floormat::swap(blk, other.blk); } template uint32_t bptr::use_count() const noexcept { if (blk && blk->_ptr) [[likely]] return blk->_hard_count; else return 0; } } // namespace floormat #ifdef __GNUG__ #pragma GCC diagnostic pop #endif