nullable value type

This commit is contained in:
BlackMATov
2022-01-24 04:13:20 +07:00
parent 6e127b41da
commit fc69b71779
3 changed files with 113 additions and 9 deletions

View File

@@ -104,7 +104,7 @@ namespace meta_hpp
{
class value final {
public:
value() = delete;
value() = default;
value(value&& other) noexcept = default;
value(const value& other) = default;
@@ -122,9 +122,12 @@ namespace meta_hpp
requires detail::stdex::copy_constructible<std::decay_t<T>>
value& operator=(T&& val);
[[nodiscard]] bool is_valid() const noexcept;
[[nodiscard]] explicit operator bool() const noexcept;
void swap(value& other) noexcept;
[[nodiscard]] const any_type& get_type() const noexcept;
[[nodiscard]] any_type get_type() const noexcept;
[[nodiscard]] void* data() noexcept;
[[nodiscard]] const void* data() const noexcept;

View File

@@ -137,34 +137,44 @@ namespace meta_hpp
return *this;
}
inline bool value::is_valid() const noexcept {
return raw_.has_value();
}
inline value::operator bool() const noexcept {
return is_valid();
}
inline void value::swap(value& other) noexcept {
using std::swap;
swap(raw_, other.raw_);
swap(traits_, other.traits_);
}
inline const any_type& value::get_type() const noexcept {
return traits_->type;
inline any_type value::get_type() const noexcept {
return traits_ != nullptr
? traits_->type
: resolve_type<void>();
}
inline void* value::data() noexcept {
return traits_->data(*this);
return traits_ != nullptr ? traits_->data(*this) : nullptr;
}
inline const void* value::data() const noexcept {
return traits_->cdata(*this);
return traits_ != nullptr ? traits_->cdata(*this) : nullptr;
}
inline const void* value::cdata() const noexcept {
return traits_->cdata(*this);
return traits_ != nullptr ? traits_->cdata(*this) : nullptr;
}
inline value value::operator*() const {
return traits_->deref(*this);
return traits_ != nullptr ? traits_->deref(*this) : value{};
}
inline value value::operator[](std::size_t index) const {
return traits_->index(*this, index);
return traits_ != nullptr ? traits_->index(*this, index) : value{};
}
template < typename T >
@@ -208,6 +218,10 @@ namespace meta_hpp
{
template < typename T >
[[nodiscard]] bool operator<(const value& l, const T& r) {
if ( !static_cast<bool>(l) ) {
return true;
}
const any_type& r_type = resolve_type<T>();
return (l.get_type() < r_type)
|| (l.get_type() == r_type && std::less<>{}(l.cast<T>(), r));
@@ -215,12 +229,24 @@ namespace meta_hpp
template < typename T >
[[nodiscard]] bool operator<(const T& l, const value& r) {
if ( !static_cast<bool>(r) ) {
return false;
}
const any_type& l_type = resolve_type<T>();
return (l_type < r.get_type())
|| (l_type == r.get_type() && std::less<>{}(l, r.cast<T>()));
}
[[nodiscard]] inline bool operator<(const value& l, const value& r) {
if ( !static_cast<bool>(r) ) {
return false;
}
if ( !static_cast<bool>(l) ) {
return true;
}
return (l.get_type() < r.get_type())
|| (l.get_type() == r.get_type() && l.traits_->less(l, r));
}
@@ -230,17 +256,33 @@ namespace meta_hpp
{
template < typename T >
[[nodiscard]] bool operator==(const value& l, const T& r) {
if ( !static_cast<bool>(l) ) {
return false;
}
return l.get_type() == resolve_type<T>()
&& std::equal_to<>{}(l.cast<T>(), r);
}
template < typename T >
[[nodiscard]] bool operator==(const T& l, const value& r) {
if ( !static_cast<bool>(r) ) {
return false;
}
return resolve_type<T>() == r.get_type()
&& std::equal_to<>{}(l, r.cast<T>());
}
[[nodiscard]] inline bool operator==(const value& l, const value& r) {
if ( static_cast<bool>(l) != static_cast<bool>(r) ) {
return false;
}
if ( !static_cast<bool>(l) ) {
return true;
}
return l.get_type() == r.get_type()
&& l.traits_->equals(l, r);
}

View File

@@ -127,6 +127,65 @@ TEST_CASE("meta/meta_utilities/value") {
const ivec2*>);
}
SUBCASE("ivec2{}") {
{
meta::value val{};
CHECK(!val);
CHECK_FALSE(val);
CHECK_FALSE(val.is_valid());
CHECK(val.data() == nullptr);
CHECK(std::as_const(val).data() == nullptr);
CHECK(std::as_const(val).cdata() == nullptr);
CHECK_FALSE(*val);
CHECK_FALSE(val[0]);
CHECK(val.try_cast<ivec2>() == nullptr);
CHECK(std::as_const(val).try_cast<ivec2>() == nullptr);
CHECK_THROWS(std::ignore = val.cast<int>());
CHECK_THROWS(std::ignore = std::as_const(val).cast<int>());
CHECK_THROWS(std::ignore = std::move(val).cast<int>());
CHECK_THROWS(std::ignore = std::move(std::as_const(val)).cast<int>());
}
{
CHECK_FALSE(meta::value{1} < meta::value{});
CHECK(meta::value{} < meta::value{1});
CHECK_FALSE(meta::value{} < meta::value{});
CHECK_FALSE(1 < meta::value{});
CHECK(meta::value{} < 1);
CHECK_FALSE(meta::value{} < meta::value{});
}
{
CHECK_FALSE(meta::value{1} == meta::value{});
CHECK_FALSE(meta::value{} == meta::value{1});
CHECK(meta::value{} == meta::value{});
CHECK_FALSE(1 == meta::value{});
CHECK_FALSE(meta::value{} == 1);
CHECK(meta::value{} == meta::value{});
}
{
CHECK(meta::value{1} != meta::value{});
CHECK(meta::value{} != meta::value{1});
CHECK_FALSE(meta::value{} != meta::value{});
CHECK(1 != meta::value{});
CHECK(meta::value{} != 1);
CHECK_FALSE(meta::value{} != meta::value{});
}
CHECK_FALSE(meta::value{} == 0);
CHECK_FALSE(meta::value{} == nullptr);
CHECK(meta::value{}.get_type() == meta::resolve_type<void>());
}
SUBCASE("ivec2&") {
ivec2 v{1,2};
ivec2& vr = v;