intial commit
This commit is contained in:
237
source/mijin/container/boxed_object.hpp
Normal file
237
source/mijin/container/boxed_object.hpp
Normal file
@@ -0,0 +1,237 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(MIJIN_CONTAINER_BOXED_OBJECT_HPP_INCLUDED)
|
||||
#define MIJIN_CONTAINER_BOXED_OBJECT_HPP_INCLUDED 1
|
||||
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include "../debug/assert.hpp"
|
||||
|
||||
namespace mijin
|
||||
{
|
||||
|
||||
//
|
||||
// public defines
|
||||
//
|
||||
|
||||
#if !defined(MIJIN_BOXED_OBJECT_DEBUG)
|
||||
#define MIJIN_BOXED_OBJECT_DEBUG MIJIN_DEBUG
|
||||
#endif
|
||||
|
||||
//
|
||||
// public constants
|
||||
//
|
||||
|
||||
//
|
||||
// public types
|
||||
//
|
||||
|
||||
template<typename T>
|
||||
class BoxedObject
|
||||
{
|
||||
private:
|
||||
union {
|
||||
T object_;
|
||||
};
|
||||
#if MIJIN_BOXED_OBJECT_DEBUG
|
||||
bool constructed = false;
|
||||
#endif
|
||||
public:
|
||||
BoxedObject() = default;
|
||||
explicit BoxedObject(T object)
|
||||
#if MIJIN_BOXED_OBJECT_DEBUG
|
||||
: constructed(true)
|
||||
#endif
|
||||
{
|
||||
std::construct_at(&object_, std::move(object));
|
||||
}
|
||||
BoxedObject(const BoxedObject&) = delete;
|
||||
BoxedObject(BoxedObject&&) = delete;
|
||||
|
||||
#if MIJIN_BOXED_OBJECT_DEBUG
|
||||
~BoxedObject()
|
||||
{
|
||||
MIJIN_ASSERT(!constructed, "BoxedObject::~BoxedObject(): Object has not been destroy prior to destructor!")
|
||||
}
|
||||
#endif
|
||||
|
||||
BoxedObject& operator=(const BoxedObject&) = delete;
|
||||
BoxedObject& operator=(BoxedObject&&) = delete;
|
||||
|
||||
template<typename... TArgs>
|
||||
void construct(TArgs&&... args)
|
||||
{
|
||||
#if MIJIN_BOXED_OBJECT_DEBUG
|
||||
MIJIN_ASSERT(!constructed, "BoxedObject::construct(): Attempt to construct an already constructed object!")
|
||||
constructed = true;
|
||||
#endif
|
||||
std::construct_at(&object_, std::forward<TArgs>(args)...);
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
#if MIJIN_BOXED_OBJECT_DEBUG
|
||||
MIJIN_ASSERT(constructed, "BoxedObject::destroy(): Attempt to destroy a not constructed object!")
|
||||
constructed = false;
|
||||
#endif
|
||||
std::destroy_at(&object_);
|
||||
}
|
||||
|
||||
void copyTo(BoxedObject& other) const
|
||||
{
|
||||
#if MIJIN_BOXED_OBJECT_DEBUG
|
||||
MIJIN_ASSERT(constructed, "BoxedObject::copy(): Attempt to copy a not constructed object!")
|
||||
#endif
|
||||
other.construct(object_);
|
||||
}
|
||||
|
||||
void moveTo(BoxedObject& other)
|
||||
{
|
||||
#if MIJIN_BOXED_OBJECT_DEBUG
|
||||
MIJIN_ASSERT(constructed, "BoxedObject::copy(): Attempt to copy a not constructed object!")
|
||||
#endif
|
||||
other.construct(std::move(object_));
|
||||
destroy();
|
||||
}
|
||||
|
||||
[[nodiscard]] T& get()
|
||||
{
|
||||
#if MIJIN_BOXED_OBJECT_DEBUG
|
||||
MIJIN_ASSERT(constructed, "BoxedObject::get(): Attempt to access a not constructed object!")
|
||||
#endif
|
||||
return object_;
|
||||
}
|
||||
|
||||
[[nodiscard]] const T& get() const
|
||||
{
|
||||
#if MIJIN_BOXED_OBJECT_DEBUG
|
||||
MIJIN_ASSERT(constructed, "BoxedObject::get(): Attempt to access a not constructed object!")
|
||||
#endif
|
||||
return object_;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class BoxedObjectIterator
|
||||
{
|
||||
public:
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = T;
|
||||
private:
|
||||
BoxedObject<T>* box_ = nullptr;
|
||||
#if MIJIN_CHECKED_ITERATORS
|
||||
BoxedObject<T>* start_ = nullptr;
|
||||
BoxedObject<T>* end_ = nullptr;
|
||||
#endif
|
||||
public:
|
||||
BoxedObjectIterator() = default;
|
||||
explicit constexpr BoxedObjectIterator(BoxedObject<T>* box, BoxedObject<T>* start, BoxedObject<T>* end)
|
||||
: box_(box)
|
||||
#if MIJIN_CHECKED_ITERATORS
|
||||
, start_(start), end_(end)
|
||||
#endif
|
||||
{}
|
||||
BoxedObjectIterator(const BoxedObjectIterator&) = default;
|
||||
BoxedObjectIterator(BoxedObjectIterator&&) noexcept = default;
|
||||
|
||||
BoxedObjectIterator& operator=(const BoxedObjectIterator&) = default;
|
||||
BoxedObjectIterator& operator=(BoxedObjectIterator&&) noexcept = default;
|
||||
BoxedObjectIterator& operator+=(difference_type diff);
|
||||
BoxedObjectIterator& operator-=(difference_type diff) { return (*this += -diff); }
|
||||
|
||||
constexpr auto operator<=>(const BoxedObjectIterator& other) const noexcept = default;
|
||||
|
||||
[[nodiscard]] T& operator*() const;
|
||||
[[nodiscard]] T* operator->() const;
|
||||
BoxedObjectIterator& operator++();
|
||||
BoxedObjectIterator operator++(int);
|
||||
BoxedObjectIterator& operator--();
|
||||
BoxedObjectIterator operator--(int);
|
||||
|
||||
[[nodiscard]] difference_type operator-(const BoxedObjectIterator& other) const { return box_ - other.box_; }
|
||||
[[nodiscard]] BoxedObjectIterator operator+(difference_type diff) const;
|
||||
[[nodiscard]] BoxedObjectIterator operator-(difference_type diff) const { return (*this + -diff); }
|
||||
|
||||
[[nodiscard]] T& operator[](difference_type diff) const { return *(*this + diff); }
|
||||
};
|
||||
template<typename T>
|
||||
inline BoxedObjectIterator<T> operator+(std::iter_difference_t<T> diff, const BoxedObjectIterator<T>& iter) {
|
||||
return iter + diff;
|
||||
}
|
||||
static_assert(std::random_access_iterator<BoxedObjectIterator<int>>);
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
template<typename T>
|
||||
BoxedObjectIterator<T>& BoxedObjectIterator<T>::operator+=(difference_type diff)
|
||||
{
|
||||
#if MIJIN_CHECKED_ITERATORS
|
||||
MIJIN_ASSERT(diff <= (end_ - box_) && diff >= (box_ - start_), "BoxedObjectIterator::operator+=(): Attempt to iterate out of range.");
|
||||
#endif
|
||||
box_ += diff;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T& BoxedObjectIterator<T>::operator*() const
|
||||
{
|
||||
#if MIJIN_CHECKED_ITERATORS
|
||||
MIJIN_ASSERT(box_ >= start_ && box < end_, "BoxedObjectIterator::operator->(): Attempt to dereference out-of-range iterator.");
|
||||
#endif
|
||||
return box_->get();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoxedObjectIterator<T>& BoxedObjectIterator<T>::operator++()
|
||||
{
|
||||
#if MIJIN_CHECKED_ITERATORS
|
||||
MIJIN_ASSERT(box_ < end_, "BoxedObjectIterator::operator++(): Attempt to iterator past the end.");
|
||||
#endif
|
||||
++box_;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoxedObjectIterator<T> BoxedObjectIterator<T>::operator++(int)
|
||||
{
|
||||
#if MIJIN_CHECKED_ITERATORS
|
||||
MIJIN_ASSERT(box_ < end_, "BoxedObjectIterator::operator++(int): Attempt to iterator past the end.");
|
||||
#endif
|
||||
BoxedObjectIterator copy(*this);
|
||||
++box_;
|
||||
return copy;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoxedObjectIterator<T>& BoxedObjectIterator<T>::operator--()
|
||||
{
|
||||
#if MIJIN_CHECKED_ITERATORS
|
||||
MIJIN_ASSERT(box_ > start_, "BoxedObjectIterator::operator--(): Attempt to iterator past start.");
|
||||
#endif
|
||||
--box_;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoxedObjectIterator<T> BoxedObjectIterator<T>::operator--(int)
|
||||
{
|
||||
#if MIJIN_CHECKED_ITERATORS
|
||||
MIJIN_ASSERT(box_ > start_, "BoxedObjectIterator::operator--(int): Attempt to iterator past start.");
|
||||
#endif
|
||||
BoxedObjectIterator copy(*this);
|
||||
--box_;
|
||||
return copy;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BoxedObjectIterator<T> BoxedObjectIterator<T>::operator+(difference_type diff) const
|
||||
{
|
||||
BoxedObjectIterator copy(*this);
|
||||
copy += diff;
|
||||
return copy;
|
||||
}
|
||||
|
||||
} // namespace mijin
|
||||
|
||||
#endif // !defined(MIJIN_CONTAINER_BOXED_OBJECT_HPP_INCLUDED)
|
||||
Reference in New Issue
Block a user