Properly constexpred and noexcepted BoxedObject.

This commit is contained in:
Patrick 2025-07-03 09:10:31 +02:00
parent 40c0d888e6
commit d29a025ec5

View File

@ -57,8 +57,8 @@ private:
bool constructed = false; bool constructed = false;
#endif #endif
public: public:
BoxedObject() noexcept : placeholder_() {}; constexpr BoxedObject() MIJIN_NOEXCEPT : placeholder_() {};
explicit BoxedObject(T object) explicit constexpr BoxedObject(T object) MIJIN_NOEXCEPT_IF(std::is_nothrow_move_constructible_v<T>)
#if MIJIN_BOXED_OBJECT_DEBUG #if MIJIN_BOXED_OBJECT_DEBUG
: constructed(true) : constructed(true)
#endif #endif
@ -69,7 +69,7 @@ public:
BoxedObject(BoxedObject&&) = delete; BoxedObject(BoxedObject&&) = delete;
#if MIJIN_BOXED_OBJECT_DEBUG #if MIJIN_BOXED_OBJECT_DEBUG
~BoxedObject() constexpr ~BoxedObject() noexcept
{ {
MIJIN_ASSERT(!constructed, "BoxedObject::~BoxedObject(): Object has not been destroyed prior to destructor!"); MIJIN_ASSERT(!constructed, "BoxedObject::~BoxedObject(): Object has not been destroyed prior to destructor!");
} }
@ -78,13 +78,13 @@ public:
BoxedObject& operator=(const BoxedObject&) = delete; BoxedObject& operator=(const BoxedObject&) = delete;
BoxedObject& operator=(BoxedObject&&) = delete; BoxedObject& operator=(BoxedObject&&) = delete;
T& operator*() noexcept { return get(); } constexpr T& operator*() noexcept { return get(); }
const T& operator*() const noexcept { return get(); } constexpr const T& operator*() const noexcept { return get(); }
T* operator->() noexcept { return &get(); } constexpr T* operator->() noexcept { return &get(); }
const T* operator->() const noexcept { return &get(); } constexpr const T* operator->() const noexcept { return &get(); }
template<typename... TArgs> template<typename... TArgs>
void construct(TArgs&&... args) constexpr void construct(TArgs&&... args) MIJIN_NOEXCEPT_IF((std::is_nothrow_constructible_v<T, TArgs...>))
{ {
#if MIJIN_BOXED_OBJECT_DEBUG #if MIJIN_BOXED_OBJECT_DEBUG
MIJIN_ASSERT(!constructed, "BoxedObject::construct(): Attempt to construct an already constructed object!"); MIJIN_ASSERT(!constructed, "BoxedObject::construct(): Attempt to construct an already constructed object!");
@ -93,7 +93,7 @@ public:
std::construct_at(&object_, std::forward<TArgs>(args)...); std::construct_at(&object_, std::forward<TArgs>(args)...);
} }
void destroy() constexpr void destroy() MIJIN_NOEXCEPT
{ {
#if MIJIN_BOXED_OBJECT_DEBUG #if MIJIN_BOXED_OBJECT_DEBUG
MIJIN_ASSERT(constructed, "BoxedObject::destroy(): Attempt to destroy a not constructed object!"); MIJIN_ASSERT(constructed, "BoxedObject::destroy(): Attempt to destroy a not constructed object!");
@ -102,7 +102,7 @@ public:
std::destroy_at(&object_); std::destroy_at(&object_);
} }
void copyTo(BoxedObject& other) const constexpr void copyTo(BoxedObject& other) const MIJIN_NOEXCEPT_IF(std::is_nothrow_copy_constructible_v<T>)
{ {
#if MIJIN_BOXED_OBJECT_DEBUG #if MIJIN_BOXED_OBJECT_DEBUG
MIJIN_ASSERT(constructed, "BoxedObject::copy(): Attempt to copy a not constructed object!"); MIJIN_ASSERT(constructed, "BoxedObject::copy(): Attempt to copy a not constructed object!");
@ -110,7 +110,7 @@ public:
other.construct(object_); other.construct(object_);
} }
void moveTo(BoxedObject& other) constexpr void moveTo(BoxedObject& other) MIJIN_NOEXCEPT_IF(std::is_nothrow_move_constructible_v<T>)
{ {
#if MIJIN_BOXED_OBJECT_DEBUG #if MIJIN_BOXED_OBJECT_DEBUG
MIJIN_ASSERT(constructed, "BoxedObject::copy(): Attempt to copy a not constructed object!"); MIJIN_ASSERT(constructed, "BoxedObject::copy(): Attempt to copy a not constructed object!");
@ -119,7 +119,7 @@ public:
destroy(); destroy();
} }
[[nodiscard]] T& get() [[nodiscard]] constexpr T& get() MIJIN_NOEXCEPT
{ {
#if MIJIN_BOXED_OBJECT_DEBUG #if MIJIN_BOXED_OBJECT_DEBUG
MIJIN_ASSERT(constructed, "BoxedObject::get(): Attempt to access a not constructed object!"); MIJIN_ASSERT(constructed, "BoxedObject::get(): Attempt to access a not constructed object!");
@ -127,7 +127,7 @@ public:
return object_; return object_;
} }
[[nodiscard]] const T& get() const [[nodiscard]] constexpr const T& get() const MIJIN_NOEXCEPT
{ {
#if MIJIN_BOXED_OBJECT_DEBUG #if MIJIN_BOXED_OBJECT_DEBUG
MIJIN_ASSERT(constructed, "BoxedObject::get(): Attempt to access a not constructed object!"); MIJIN_ASSERT(constructed, "BoxedObject::get(): Attempt to access a not constructed object!");
@ -149,38 +149,38 @@ private:
BoxedObject<T>* end_ = nullptr; BoxedObject<T>* end_ = nullptr;
#endif #endif
public: public:
BoxedObjectIterator() = default; BoxedObjectIterator() noexcept = default;
explicit constexpr BoxedObjectIterator(BoxedObject<T>* box, BoxedObject<T>* start, BoxedObject<T>* end) explicit constexpr BoxedObjectIterator(BoxedObject<T>* box, BoxedObject<T>* start, BoxedObject<T>* end) MIJIN_NOEXCEPT
: box_(box) : box_(box)
#if MIJIN_CHECKED_ITERATORS #if MIJIN_CHECKED_ITERATORS
, start_(start), end_(end) , start_(start), end_(end)
#endif #endif
{} {}
BoxedObjectIterator(const BoxedObjectIterator&) = default; constexpr BoxedObjectIterator(const BoxedObjectIterator&) noexcept = default;
BoxedObjectIterator(BoxedObjectIterator&&) noexcept = default; constexpr BoxedObjectIterator(BoxedObjectIterator&&) noexcept = default;
BoxedObjectIterator& operator=(const BoxedObjectIterator&) = default; constexpr BoxedObjectIterator& operator=(const BoxedObjectIterator&) noexcept = default;
BoxedObjectIterator& operator=(BoxedObjectIterator&&) noexcept = default; constexpr BoxedObjectIterator& operator=(BoxedObjectIterator&&) noexcept = default;
BoxedObjectIterator& operator+=(difference_type diff); constexpr BoxedObjectIterator& operator+=(difference_type diff) MIJIN_NOEXCEPT;
BoxedObjectIterator& operator-=(difference_type diff) { return (*this += -diff); } constexpr BoxedObjectIterator& operator-=(difference_type diff) MIJIN_NOEXCEPT { return (*this += -diff); }
constexpr auto operator<=>(const BoxedObjectIterator& other) const noexcept = default; constexpr auto operator<=>(const BoxedObjectIterator& other) const noexcept = default;
[[nodiscard]] T& operator*() const; [[nodiscard]] constexpr T& operator*() const MIJIN_NOEXCEPT;
[[nodiscard]] T* operator->() const; [[nodiscard]] constexpr T* operator->() const MIJIN_NOEXCEPT;
BoxedObjectIterator& operator++(); constexpr BoxedObjectIterator& operator++() MIJIN_NOEXCEPT;
BoxedObjectIterator operator++(int); constexpr BoxedObjectIterator operator++(int) MIJIN_NOEXCEPT;
BoxedObjectIterator& operator--(); constexpr BoxedObjectIterator& operator--() MIJIN_NOEXCEPT;
BoxedObjectIterator operator--(int); constexpr BoxedObjectIterator operator--(int) MIJIN_NOEXCEPT;
[[nodiscard]] difference_type operator-(const BoxedObjectIterator& other) const { return box_ - other.box_; } [[nodiscard]] constexpr difference_type operator-(const BoxedObjectIterator& other) const MIJIN_NOEXCEPT { return box_ - other.box_; }
[[nodiscard]] BoxedObjectIterator operator+(difference_type diff) const; [[nodiscard]] constexpr BoxedObjectIterator operator+(difference_type diff) const MIJIN_NOEXCEPT;
[[nodiscard]] BoxedObjectIterator operator-(difference_type diff) const { return (*this + -diff); } [[nodiscard]] constexpr BoxedObjectIterator operator-(difference_type diff) const MIJIN_NOEXCEPT { return (*this + -diff); }
[[nodiscard]] T& operator[](difference_type diff) const { return *(*this + diff); } [[nodiscard]] T& operator[](difference_type diff) const MIJIN_NOEXCEPT { return *(*this + diff); }
}; };
template<typename T> template<typename T>
inline BoxedObjectIterator<T> operator+(std::iter_difference_t<T> diff, const BoxedObjectIterator<T>& iter) { constexpr BoxedObjectIterator<T> operator+(std::iter_difference_t<T> diff, const BoxedObjectIterator<T>& iter) MIJIN_NOEXCEPT {
return iter + diff; return iter + diff;
} }
static_assert(std::random_access_iterator<BoxedObjectIterator<int>>); static_assert(std::random_access_iterator<BoxedObjectIterator<int>>);
@ -190,7 +190,7 @@ static_assert(std::random_access_iterator<BoxedObjectIterator<int>>);
// //
template<typename T> template<typename T>
BoxedObjectIterator<T>& BoxedObjectIterator<T>::operator+=(difference_type diff) constexpr BoxedObjectIterator<T>& BoxedObjectIterator<T>::operator+=(difference_type diff) MIJIN_NOEXCEPT
{ {
#if MIJIN_CHECKED_ITERATORS #if MIJIN_CHECKED_ITERATORS
MIJIN_ASSERT(diff <= (end_ - box_) && diff >= (box_ - start_), "BoxedObjectIterator::operator+=(): Attempt to iterate out of range."); MIJIN_ASSERT(diff <= (end_ - box_) && diff >= (box_ - start_), "BoxedObjectIterator::operator+=(): Attempt to iterate out of range.");
@ -200,7 +200,7 @@ BoxedObjectIterator<T>& BoxedObjectIterator<T>::operator+=(difference_type diff)
} }
template<typename T> template<typename T>
T& BoxedObjectIterator<T>::operator*() const constexpr T& BoxedObjectIterator<T>::operator*() const MIJIN_NOEXCEPT
{ {
#if MIJIN_CHECKED_ITERATORS #if MIJIN_CHECKED_ITERATORS
MIJIN_ASSERT(box_ >= start_ && box_ < end_, "BoxedObjectIterator::operator->(): Attempt to dereference out-of-range iterator."); MIJIN_ASSERT(box_ >= start_ && box_ < end_, "BoxedObjectIterator::operator->(): Attempt to dereference out-of-range iterator.");
@ -209,7 +209,7 @@ T& BoxedObjectIterator<T>::operator*() const
} }
template<typename T> template<typename T>
BoxedObjectIterator<T>& BoxedObjectIterator<T>::operator++() constexpr BoxedObjectIterator<T>& BoxedObjectIterator<T>::operator++() MIJIN_NOEXCEPT
{ {
#if MIJIN_CHECKED_ITERATORS #if MIJIN_CHECKED_ITERATORS
MIJIN_ASSERT(box_ < end_, "BoxedObjectIterator::operator++(): Attempt to iterator past the end."); MIJIN_ASSERT(box_ < end_, "BoxedObjectIterator::operator++(): Attempt to iterator past the end.");
@ -218,7 +218,7 @@ BoxedObjectIterator<T>& BoxedObjectIterator<T>::operator++()
} }
template<typename T> template<typename T>
BoxedObjectIterator<T> BoxedObjectIterator<T>::operator++(int) constexpr BoxedObjectIterator<T> BoxedObjectIterator<T>::operator++(int) MIJIN_NOEXCEPT
{ {
#if MIJIN_CHECKED_ITERATORS #if MIJIN_CHECKED_ITERATORS
MIJIN_ASSERT(box_ < end_, "BoxedObjectIterator::operator++(int): Attempt to iterator past the end."); MIJIN_ASSERT(box_ < end_, "BoxedObjectIterator::operator++(int): Attempt to iterator past the end.");
@ -229,7 +229,7 @@ BoxedObjectIterator<T> BoxedObjectIterator<T>::operator++(int)
} }
template<typename T> template<typename T>
BoxedObjectIterator<T>& BoxedObjectIterator<T>::operator--() constexpr BoxedObjectIterator<T>& BoxedObjectIterator<T>::operator--() MIJIN_NOEXCEPT
{ {
#if MIJIN_CHECKED_ITERATORS #if MIJIN_CHECKED_ITERATORS
MIJIN_ASSERT(box_ > start_, "BoxedObjectIterator::operator--(): Attempt to iterator past start."); MIJIN_ASSERT(box_ > start_, "BoxedObjectIterator::operator--(): Attempt to iterator past start.");
@ -238,7 +238,7 @@ BoxedObjectIterator<T>& BoxedObjectIterator<T>::operator--()
} }
template<typename T> template<typename T>
BoxedObjectIterator<T> BoxedObjectIterator<T>::operator--(int) constexpr BoxedObjectIterator<T> BoxedObjectIterator<T>::operator--(int) MIJIN_NOEXCEPT
{ {
#if MIJIN_CHECKED_ITERATORS #if MIJIN_CHECKED_ITERATORS
MIJIN_ASSERT(box_ > start_, "BoxedObjectIterator::operator--(int): Attempt to iterator past start."); MIJIN_ASSERT(box_ > start_, "BoxedObjectIterator::operator--(int): Attempt to iterator past start.");
@ -249,7 +249,7 @@ BoxedObjectIterator<T> BoxedObjectIterator<T>::operator--(int)
} }
template<typename T> template<typename T>
BoxedObjectIterator<T> BoxedObjectIterator<T>::operator+(difference_type diff) const constexpr BoxedObjectIterator<T> BoxedObjectIterator<T>::operator+(difference_type diff) const MIJIN_NOEXCEPT
{ {
BoxedObjectIterator copy(*this); BoxedObjectIterator copy(*this);
copy += diff; copy += diff;