mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-14 19:41:29 +07:00
uvalue simplifying and usage example
This commit is contained in:
@@ -61,40 +61,15 @@ namespace meta_hpp
|
||||
[[nodiscard]] uvalue operator[](std::size_t index) const;
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] T get_as() &;
|
||||
template < typename T >
|
||||
[[nodiscard]] T get_as() &&;
|
||||
template < typename T >
|
||||
[[nodiscard]] T get_as() const &;
|
||||
template < typename T >
|
||||
[[nodiscard]] T get_as() const &&;
|
||||
[[nodiscard]] auto get_as()
|
||||
-> std::conditional_t<detail::pointer_kind<T>, T, T&>;
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] T& get_as_ref() &;
|
||||
template < typename T >
|
||||
[[nodiscard]] T&& get_as_ref() &&;
|
||||
template < typename T >
|
||||
[[nodiscard]] const T& get_as_ref() const &;
|
||||
template < typename T >
|
||||
[[nodiscard]] const T&& get_as_ref() const &&;
|
||||
[[nodiscard]] auto get_as() const
|
||||
-> std::conditional_t<detail::pointer_kind<T>, T, const T&>;
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] bool can_get_as() &;
|
||||
template < typename T >
|
||||
[[nodiscard]] bool can_get_as() &&;
|
||||
template < typename T >
|
||||
[[nodiscard]] bool can_get_as() const &;
|
||||
template < typename T >
|
||||
[[nodiscard]] bool can_get_as() const &&;
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] bool can_get_as_ref() &;
|
||||
template < typename T >
|
||||
[[nodiscard]] bool can_get_as_ref() &&;
|
||||
template < typename T >
|
||||
[[nodiscard]] bool can_get_as_ref() const &;
|
||||
template < typename T >
|
||||
[[nodiscard]] bool can_get_as_ref() const &&;
|
||||
[[nodiscard]] bool can_get_as() const noexcept;
|
||||
|
||||
friend bool operator<(const uvalue& l, const uvalue& r);
|
||||
friend bool operator==(const uvalue& l, const uvalue& r);
|
||||
@@ -116,18 +91,3 @@ namespace meta_hpp
|
||||
l.swap(r);
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename T, detail::decay_value_kind V >
|
||||
[[nodiscard]] auto get_as(V&& value) -> T;
|
||||
|
||||
template < typename T, detail::decay_value_kind V >
|
||||
[[nodiscard]] auto get_as_ref(V&& value) -> detail::add_cvref_t<V&&, T>;
|
||||
|
||||
template < typename T, detail::decay_value_kind V >
|
||||
[[nodiscard]] bool can_get_as(V&& value) noexcept;
|
||||
|
||||
template < typename T, detail::decay_value_kind V >
|
||||
[[nodiscard]] bool can_get_as_ref(V&& value) noexcept;
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ namespace meta_hpp
|
||||
|
||||
.deref = +[]([[maybe_unused]] const uvalue& v) -> uvalue {
|
||||
if constexpr ( detail::has_deref_traits<Tp> ) {
|
||||
return detail::deref_traits<Tp>{}(v.get_as_ref<Tp>());
|
||||
return detail::deref_traits<Tp>{}(v.get_as<Tp>());
|
||||
} else {
|
||||
detail::throw_exception_with("value type doesn't have value deref traits");
|
||||
}
|
||||
@@ -194,7 +194,7 @@ namespace meta_hpp
|
||||
|
||||
.index = +[]([[maybe_unused]] const uvalue& v, [[maybe_unused]] std::size_t i) -> uvalue {
|
||||
if constexpr ( detail::has_index_traits<Tp> ) {
|
||||
return detail::index_traits<Tp>{}(v.get_as_ref<Tp>(), i);
|
||||
return detail::index_traits<Tp>{}(v.get_as<Tp>(), i);
|
||||
} else {
|
||||
detail::throw_exception_with("value type doesn't have value index traits");
|
||||
}
|
||||
@@ -202,7 +202,7 @@ namespace meta_hpp
|
||||
|
||||
.less = +[]([[maybe_unused]] const uvalue& l, [[maybe_unused]] const uvalue& r) -> bool {
|
||||
if constexpr ( detail::has_less_traits<Tp> ) {
|
||||
return detail::less_traits<Tp>{}(l.get_as_ref<Tp>(), r.get_as_ref<Tp>());
|
||||
return detail::less_traits<Tp>{}(l.get_as<Tp>(), r.get_as<Tp>());
|
||||
} else {
|
||||
detail::throw_exception_with("value type doesn't have value less traits");
|
||||
}
|
||||
@@ -210,23 +210,23 @@ namespace meta_hpp
|
||||
|
||||
.equals = +[]([[maybe_unused]] const uvalue& l, [[maybe_unused]] const uvalue& r) -> bool {
|
||||
if constexpr ( detail::has_equals_traits<Tp> ) {
|
||||
return detail::equals_traits<Tp>{}(l.get_as_ref<Tp>(), r.get_as_ref<Tp>());
|
||||
return detail::equals_traits<Tp>{}(l.get_as<Tp>(), r.get_as<Tp>());
|
||||
} else {
|
||||
detail::throw_exception_with("value type doesn't have value equals traits");
|
||||
}
|
||||
},
|
||||
|
||||
.istream = +[]([[maybe_unused]] std::istream& is, [[maybe_unused]] uvalue& v) -> std::istream& {
|
||||
if constexpr ( detail::has_istream_traits<Tp> ) {
|
||||
return detail::istream_traits<Tp>{}(is, v.get_as_ref<Tp>());
|
||||
if constexpr ( detail::has_istream_traits<Tp> && !detail::pointer_kind<Tp> ) {
|
||||
return detail::istream_traits<Tp>{}(is, v.get_as<Tp>());
|
||||
} else {
|
||||
detail::throw_exception_with("value type doesn't have value istream traits");
|
||||
}
|
||||
},
|
||||
|
||||
.ostream = +[]([[maybe_unused]] std::ostream& os, [[maybe_unused]] const uvalue& v) -> std::ostream& {
|
||||
if constexpr ( detail::has_ostream_traits<Tp> ) {
|
||||
return detail::ostream_traits<Tp>{}(os, v.get_as_ref<Tp>());
|
||||
if constexpr ( detail::has_ostream_traits<Tp> && !detail::pointer_kind<Tp> ) {
|
||||
return detail::ostream_traits<Tp>{}(os, v.get_as<Tp>());
|
||||
} else {
|
||||
detail::throw_exception_with("value type doesn't have value ostream traits");
|
||||
}
|
||||
@@ -327,106 +327,15 @@ namespace meta_hpp
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
T uvalue::get_as() & {
|
||||
return meta_hpp::get_as<T>(*this);
|
||||
}
|
||||
auto uvalue::get_as() -> std::conditional_t<detail::pointer_kind<T>, T, T&> {
|
||||
static_assert(std::is_same_v<T, std::decay_t<T>>);
|
||||
|
||||
template < typename T >
|
||||
T uvalue::get_as() && {
|
||||
return meta_hpp::get_as<T>(std::move(*this));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
T uvalue::get_as() const & {
|
||||
return meta_hpp::get_as<T>(*this);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
T uvalue::get_as() const && {
|
||||
// NOLINTNEXTLINE(*-move-const-arg)
|
||||
return meta_hpp::get_as<T>(std::move(*this));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
T& uvalue::get_as_ref() & {
|
||||
return meta_hpp::get_as_ref<T>(*this);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
T&& uvalue::get_as_ref() && {
|
||||
return meta_hpp::get_as_ref<T>(std::move(*this));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
const T& uvalue::get_as_ref() const & {
|
||||
return meta_hpp::get_as_ref<T>(*this);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
const T&& uvalue::get_as_ref() const && {
|
||||
// NOLINTNEXTLINE(*-move-const-arg)
|
||||
return meta_hpp::get_as_ref<T>(std::move(*this));
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
template < typename T >
|
||||
bool uvalue::can_get_as() & {
|
||||
return meta_hpp::can_get_as<T>(*this);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
bool uvalue::can_get_as() && {
|
||||
return meta_hpp::can_get_as<T>(std::move(*this));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
bool uvalue::can_get_as() const & {
|
||||
return meta_hpp::can_get_as<T>(*this);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
bool uvalue::can_get_as() const && {
|
||||
// NOLINTNEXTLINE(*-move-const-arg)
|
||||
return meta_hpp::can_get_as<T>(std::move(*this));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
bool uvalue::can_get_as_ref() & {
|
||||
return meta_hpp::can_get_as_ref<T>(*this);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
bool uvalue::can_get_as_ref() && {
|
||||
return meta_hpp::can_get_as_ref<T>(std::move(*this));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
bool uvalue::can_get_as_ref() const & {
|
||||
return meta_hpp::can_get_as_ref<T>(*this);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
bool uvalue::can_get_as_ref() const && {
|
||||
// NOLINTNEXTLINE(*-move-const-arg)
|
||||
return meta_hpp::can_get_as_ref<T>(std::move(*this));
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename T, detail::decay_value_kind V >
|
||||
[[nodiscard]] auto get_as(V&& value) -> T {
|
||||
using Tp = std::decay_t<T>;
|
||||
static_assert(std::is_constructible_v<T, detail::add_cvref_t<V&&, Tp>>);
|
||||
|
||||
const any_type& from_type = value.get_type();
|
||||
const any_type& to_type = resolve_type<Tp>();
|
||||
const any_type& from_type = get_type();
|
||||
const any_type& to_type = resolve_type<T>();
|
||||
|
||||
if ( from_type == to_type ) {
|
||||
using to_ptr_t = detail::add_cv_t<V, Tp>*;
|
||||
auto to_ptr = static_cast<to_ptr_t>(value.data());
|
||||
return static_cast<T>(*to_ptr);
|
||||
T* to_ptr = static_cast<T*>(data());
|
||||
return *to_ptr;
|
||||
}
|
||||
|
||||
const auto is_a = [](const any_type& base, const any_type& derived){
|
||||
@@ -438,12 +347,11 @@ namespace meta_hpp
|
||||
const class_type& to_class = to_type.as_class();
|
||||
const class_type& from_class = from_type.as_class();
|
||||
|
||||
using to_ptr_t = detail::add_cv_t<V, Tp>*;
|
||||
auto to_ptr = static_cast<to_ptr_t>(detail::pointer_upcast(value.data(), from_class, to_class));
|
||||
return static_cast<T>(*to_ptr);
|
||||
T* to_ptr = static_cast<T*>(detail::pointer_upcast(data(), from_class, to_class));
|
||||
return *to_ptr;
|
||||
}
|
||||
|
||||
if constexpr ( std::is_pointer_v<T> ) {
|
||||
if constexpr ( detail::pointer_kind<T> ) {
|
||||
if ( to_type.is_pointer() && from_type.is_nullptr() ) {
|
||||
return static_cast<T>(nullptr);
|
||||
}
|
||||
@@ -459,11 +367,11 @@ namespace meta_hpp
|
||||
const any_type& from_data_type = from_type_ptr.get_data_type();
|
||||
|
||||
if ( to_type_ptr_readonly >= from_type_ptr_readonly ) {
|
||||
using from_data_ptr_t = detail::add_cv_t<V, void*>*;
|
||||
auto from_data_ptr = static_cast<from_data_ptr_t>(value.data());
|
||||
void** from_data_ptr = static_cast<void**>(data());
|
||||
|
||||
if ( to_data_type.is_void() || to_data_type == from_data_type ) {
|
||||
return static_cast<T>(*from_data_ptr);
|
||||
void* to_ptr = *from_data_ptr;
|
||||
return static_cast<T>(to_ptr);
|
||||
}
|
||||
|
||||
if ( is_a(to_data_type, from_data_type) ) {
|
||||
@@ -480,19 +388,74 @@ namespace meta_hpp
|
||||
detail::throw_exception_with("bad value cast");
|
||||
}
|
||||
|
||||
template < typename T, detail::decay_value_kind V >
|
||||
[[nodiscard]] auto get_as_ref(V&& value) -> detail::add_cvref_t<V&&, T> {
|
||||
static_assert(!std::is_reference_v<T>);
|
||||
return get_as<detail::add_cvref_t<V&&, T>>(std::forward<V>(value));
|
||||
template < typename T >
|
||||
auto uvalue::get_as() const -> std::conditional_t<detail::pointer_kind<T>, T, const T&> {
|
||||
static_assert(std::is_same_v<T, std::decay_t<T>>);
|
||||
|
||||
const any_type& from_type = get_type();
|
||||
const any_type& to_type = resolve_type<T>();
|
||||
|
||||
if ( from_type == to_type ) {
|
||||
const T* to_ptr = static_cast<const T*>(data());
|
||||
return *to_ptr;
|
||||
}
|
||||
|
||||
const auto is_a = [](const any_type& base, const any_type& derived){
|
||||
return (base == derived)
|
||||
|| (base.is_class() && derived.is_class() && base.as_class().is_base_of(derived.as_class()));
|
||||
};
|
||||
|
||||
if ( is_a(to_type, from_type) ) {
|
||||
const class_type& to_class = to_type.as_class();
|
||||
const class_type& from_class = from_type.as_class();
|
||||
|
||||
const T* to_ptr = static_cast<const T*>(detail::pointer_upcast(data(), from_class, to_class));
|
||||
return *to_ptr;
|
||||
}
|
||||
|
||||
if constexpr ( detail::pointer_kind<T> ) {
|
||||
if ( to_type.is_pointer() && from_type.is_nullptr() ) {
|
||||
return static_cast<T>(nullptr);
|
||||
}
|
||||
|
||||
if ( to_type.is_pointer() && from_type.is_pointer() ) {
|
||||
const pointer_type& to_type_ptr = to_type.as_pointer();
|
||||
const bool to_type_ptr_readonly = to_type_ptr.get_flags().has(pointer_flags::is_readonly);
|
||||
|
||||
const pointer_type& from_type_ptr = from_type.as_pointer();
|
||||
const bool from_type_ptr_readonly = from_type_ptr.get_flags().has(pointer_flags::is_readonly);
|
||||
|
||||
const any_type& to_data_type = to_type_ptr.get_data_type();
|
||||
const any_type& from_data_type = from_type_ptr.get_data_type();
|
||||
|
||||
if ( to_type_ptr_readonly >= from_type_ptr_readonly ) {
|
||||
void* const* from_data_ptr = static_cast<void* const*>(data());
|
||||
|
||||
if ( to_data_type.is_void() || to_data_type == from_data_type ) {
|
||||
void* to_ptr = *from_data_ptr;
|
||||
return static_cast<T>(to_ptr);
|
||||
}
|
||||
|
||||
if ( is_a(to_data_type, from_data_type) ) {
|
||||
const class_type& to_data_class = to_data_type.as_class();
|
||||
const class_type& from_data_class = from_data_type.as_class();
|
||||
|
||||
void* to_ptr = detail::pointer_upcast(*from_data_ptr, from_data_class, to_data_class);
|
||||
return static_cast<T>(to_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
detail::throw_exception_with("bad value cast");
|
||||
}
|
||||
|
||||
template < typename T, detail::decay_value_kind V >
|
||||
[[nodiscard]] bool can_get_as(V&& value) noexcept {
|
||||
using Tp = std::decay_t<T>;
|
||||
static_assert(std::is_constructible_v<T, detail::add_cvref_t<V&&, Tp>>);
|
||||
template < typename T >
|
||||
bool uvalue::can_get_as() const noexcept {
|
||||
static_assert(std::is_same_v<T, std::decay_t<T>>);
|
||||
|
||||
const any_type& from_type = value.get_type();
|
||||
const any_type& to_type = resolve_type<Tp>();
|
||||
const any_type& from_type = get_type();
|
||||
const any_type& to_type = resolve_type<T>();
|
||||
|
||||
if ( from_type == to_type ) {
|
||||
return true;
|
||||
@@ -507,7 +470,7 @@ namespace meta_hpp
|
||||
return true;
|
||||
}
|
||||
|
||||
if constexpr ( std::is_pointer_v<T> ) {
|
||||
if constexpr ( detail::pointer_kind<T> ) {
|
||||
if ( to_type.is_pointer() && from_type.is_nullptr() ) {
|
||||
return true;
|
||||
}
|
||||
@@ -532,12 +495,6 @@ namespace meta_hpp
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template < typename T, detail::decay_value_kind V >
|
||||
[[nodiscard]] bool can_get_as_ref(V&& value) noexcept {
|
||||
static_assert(!std::is_reference_v<T>);
|
||||
return can_get_as<detail::add_cvref_t<V&&, T>>(std::forward<V>(value));
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
@@ -551,7 +508,7 @@ namespace meta_hpp
|
||||
const any_type& l_type = l.get_type();
|
||||
const any_type& r_type = resolve_type<T>();
|
||||
|
||||
return (l_type < r_type) || (l_type == r_type && l.get_as_ref<T>() < r);
|
||||
return (l_type < r_type) || (l_type == r_type && l.get_as<T>() < r);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
@@ -563,7 +520,7 @@ namespace meta_hpp
|
||||
const any_type& l_type = resolve_type<T>();
|
||||
const any_type& r_type = r.get_type();
|
||||
|
||||
return (l_type < r_type) || (l_type == r_type && l < r.get_as_ref<T>());
|
||||
return (l_type < r_type) || (l_type == r_type && l < r.get_as<T>());
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool operator<(const uvalue& l, const uvalue& r) {
|
||||
@@ -593,7 +550,7 @@ namespace meta_hpp
|
||||
const any_type& l_type = l.get_type();
|
||||
const any_type& r_type = resolve_type<T>();
|
||||
|
||||
return l_type == r_type && l.get_as_ref<T>() == r;
|
||||
return l_type == r_type && l.get_as<T>() == r;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
@@ -605,7 +562,7 @@ namespace meta_hpp
|
||||
const any_type& l_type = resolve_type<T>();
|
||||
const any_type& r_type = r.get_type();
|
||||
|
||||
return l_type == r_type && l == r.get_as_ref<T>();
|
||||
return l_type == r_type && l == r.get_as<T>();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool operator==(const uvalue& l, const uvalue& r) {
|
||||
|
||||
Reference in New Issue
Block a user