Added property type.
This commit is contained in:
parent
b66893dda7
commit
0a4f1d2ce4
107
source/mijin/util/property.hpp
Normal file
107
source/mijin/util/property.hpp
Normal file
@ -0,0 +1,107 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef MIJIN_UTIL_PROPERTY_HPP_INCLUDED
|
||||
#define MIJIN_UTIL_PROPERTY_HPP_INCLUDED 1
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include "../debug/assert.hpp"
|
||||
|
||||
namespace mijin
|
||||
{
|
||||
|
||||
//
|
||||
// public defines
|
||||
//
|
||||
|
||||
//
|
||||
// public types
|
||||
//
|
||||
|
||||
template<typename T, typename TGet = const T&, typename TSet = T>
|
||||
class PropertyStorage
|
||||
{
|
||||
public:
|
||||
using value_t = T;
|
||||
using get_t = TGet;
|
||||
using set_t = TSet;
|
||||
|
||||
virtual ~PropertyStorage() noexcept = default;
|
||||
|
||||
[[nodiscard]] virtual TGet getValue() = 0;
|
||||
virtual void setValue(TSet value) = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class SimplePropertyStorage : public PropertyStorage<T>
|
||||
{
|
||||
private:
|
||||
T value_;
|
||||
public:
|
||||
SimplePropertyStorage() noexcept = default;
|
||||
SimplePropertyStorage(const SimplePropertyStorage& other) noexcept(noexcept(T(other.value_))) = default;
|
||||
SimplePropertyStorage(SimplePropertyStorage&& other) noexcept(noexcept(T(std::move(other.value_)))) = default;
|
||||
explicit SimplePropertyStorage(T value) noexcept(noexcept(T(std::move(value)))) : value_(std::move(value)) {}
|
||||
|
||||
SimplePropertyStorage& operator=(const SimplePropertyStorage& other) noexcept(noexcept(value_ = other.value_)) = default;
|
||||
SimplePropertyStorage& operator=(SimplePropertyStorage&& other) noexcept(noexcept(value_ = std::move(other.value_))) = default;
|
||||
|
||||
const T& getValue() noexcept override { return value_; }
|
||||
void setValue(T value) override { value_ = std::move(value); }
|
||||
};
|
||||
|
||||
template<typename T, typename TGet = const T&, typename TSet = T>
|
||||
class Property
|
||||
{
|
||||
private:
|
||||
using storage_t = PropertyStorage<T, TGet, TSet>;
|
||||
using storage_ptr_t = std::unique_ptr<storage_t>;
|
||||
|
||||
storage_ptr_t storage_;
|
||||
public:
|
||||
class PropertyProxy
|
||||
{
|
||||
private:
|
||||
Property* base_;
|
||||
public:
|
||||
explicit PropertyProxy(Property* base) noexcept : base_(base) {}
|
||||
|
||||
operator TGet() noexcept { return base_->get(); }
|
||||
PropertyProxy& operator=(TSet value) noexcept(noexcept(std::declval<T&>() = std::move(value)))
|
||||
{
|
||||
base_->set(std::move(value));
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
Property() noexcept = default;
|
||||
explicit Property(storage_ptr_t storage) noexcept : storage_(std::move(storage)) {}
|
||||
Property(Property&&) noexcept = default;
|
||||
|
||||
Property& operator=(Property&&) noexcept = default;
|
||||
PropertyProxy operator*() noexcept { return PropertyProxy(this); }
|
||||
|
||||
[[nodiscard]] TGet get() noexcept
|
||||
{
|
||||
MIJIN_ASSERT_FATAL(storage_ != nullptr, "Cannot get value from an unset property.");
|
||||
return storage_->getValue();
|
||||
}
|
||||
void set(TSet value) noexcept(noexcept(std::declval<T&>() = std::move(value)))
|
||||
{
|
||||
MIJIN_ASSERT_FATAL(storage_ != nullptr, "Cannot set value of an unset property.");
|
||||
storage_->setValue(std::move<TSet>(value));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename TStorage>
|
||||
Property(std::unique_ptr<TStorage>) -> Property<typename TStorage::value_t, typename TStorage::get_t, typename TStorage::set_t>;
|
||||
|
||||
template<typename T>
|
||||
Property<T> makeSimpleProperty(T value) noexcept(noexcept(std::declval<T&>() = std::move(value)))
|
||||
{
|
||||
return Property(std::make_unique<SimplePropertyStorage<T>>(std::move(value)));
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MIJIN_UTIL_PROPERTY_HPP_INCLUDED
|
||||
Loading…
x
Reference in New Issue
Block a user