From 558e7b134226309d5ae2bd6f21148484200f2731 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Sun, 6 Nov 2022 01:34:35 +0700 Subject: [PATCH] regen singles --- manuals/meta_examples/function_example.cpp | 2 +- manuals/meta_examples/member_example.cpp | 2 +- manuals/meta_examples/variable_example.cpp | 2 +- singles/headers/meta.hpp/meta_all.hpp | 362 +++++++++++++++++---- 4 files changed, 307 insertions(+), 61 deletions(-) diff --git a/manuals/meta_examples/function_example.cpp b/manuals/meta_examples/function_example.cpp index 9e2d481..b54a553 100644 --- a/manuals/meta_examples/function_example.cpp +++ b/manuals/meta_examples/function_example.cpp @@ -65,7 +65,7 @@ TEST_CASE("meta/meta_examples/function/usage") { CHECK(sub_result_value.get_type() == meta::resolve_type()); // casts the dynamic returned value to the typed value - const int sub_function_typed_result = sub_result_value.cast(); + const int sub_function_typed_result = sub_result_value.get_as(); // here is our typed result CHECK(sub_function_typed_result == 42); diff --git a/manuals/meta_examples/member_example.cpp b/manuals/meta_examples/member_example.cpp index 252a0b6..da73971 100644 --- a/manuals/meta_examples/member_example.cpp +++ b/manuals/meta_examples/member_example.cpp @@ -56,7 +56,7 @@ TEST_CASE("meta/meta_examples/member/usage") { CHECK(ivec2_x_value.get_type() == meta::resolve_type()); // casts the dynamic value to the typed value - const int ivec2_x_typed_value = ivec2_x_value.cast(); + const int ivec2_x_typed_value = ivec2_x_value.get_as(); // here is our member typed value CHECK(ivec2_x_typed_value == 42); diff --git a/manuals/meta_examples/variable_example.cpp b/manuals/meta_examples/variable_example.cpp index 7e25d62..d7563d8 100644 --- a/manuals/meta_examples/variable_example.cpp +++ b/manuals/meta_examples/variable_example.cpp @@ -34,7 +34,7 @@ TEST_CASE("meta/meta_examples/variable/usage") { CHECK(pi_variable_value.get_type() == meta::resolve_type()); // checks the typed variable value - CHECK(pi_variable_value.cast() == doctest::Approx(3.14).epsilon(0.01)); + CHECK(pi_variable_value.get_as() == doctest::Approx(3.14).epsilon(0.01)); // we can change variable values, but only non-const CHECK_THROWS(pi_variable.set(6.0)); diff --git a/singles/headers/meta.hpp/meta_all.hpp b/singles/headers/meta.hpp/meta_all.hpp index 9a5a090..51b5bf2 100644 --- a/singles/headers/meta.hpp/meta_all.hpp +++ b/singles/headers/meta.hpp/meta_all.hpp @@ -192,6 +192,43 @@ namespace meta_hpp::detail return ::meta_hpp::detail::bitflags(l) ^ ::meta_hpp::detail::bitflags(r);\ } +namespace meta_hpp::detail +{ + template < typename From > + struct cv_traits { + static constexpr bool is_const = std::is_const_v>; + static constexpr bool is_volatile = std::is_volatile_v>; + + template < bool yesno, template < typename > typename Q, typename V > + using apply_t_if = std::conditional_t, V>; + + template < typename To > + using add_to = + apply_t_if>; + + template < typename To > + using copy_to = add_to>; + }; + + template < typename From, typename To > + struct add_cv { + using type = typename cv_traits::template add_to; + }; + + template < typename From, typename To > + struct copy_cv { + using type = typename cv_traits::template copy_to; + }; + + template < typename From, typename To > + using add_cv_t = typename add_cv::type; + + template < typename From, typename To > + using copy_cv_t = typename copy_cv::type; +} + namespace meta_hpp::detail { template < typename From > @@ -205,12 +242,20 @@ namespace meta_hpp::detail using apply_t_if = std::conditional_t, V>; template < typename To > - using copy_to = + using add_to = apply_t_if>>>>; + To>>>>; + + template < typename To > + using copy_to = add_to>; + }; + + template < typename From, typename To > + struct add_cvref { + using type = typename cvref_traits::template add_to; }; template < typename From, typename To > @@ -218,6 +263,9 @@ namespace meta_hpp::detail using type = typename cvref_traits::template copy_to; }; + template < typename From, typename To > + using add_cvref_t = typename add_cvref::type; + template < typename From, typename To > using copy_cvref_t = typename copy_cvref::type; } @@ -2215,22 +2263,40 @@ namespace meta_hpp [[nodiscard]] uvalue operator[](std::size_t index) const; template < typename T > - [[nodiscard]] std::decay_t& cast() &; + [[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 &&; template < typename T > - [[nodiscard]] std::decay_t&& cast() &&; + [[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 &&; template < typename T > - [[nodiscard]] const std::decay_t& cast() const &; + [[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]] const std::decay_t&& cast() const &&; - + [[nodiscard]] bool can_get_as_ref() &; template < typename T > - [[nodiscard]] std::decay_t* try_cast() noexcept; - + [[nodiscard]] bool can_get_as_ref() &&; template < typename T > - [[nodiscard]] const std::decay_t* try_cast() const noexcept; + [[nodiscard]] bool can_get_as_ref() const &; + template < typename T > + [[nodiscard]] bool can_get_as_ref() const &&; friend bool operator<(const uvalue& l, const uvalue& r); friend bool operator==(const uvalue& l, const uvalue& r); @@ -2253,6 +2319,21 @@ namespace meta_hpp } } +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; + + 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; +} + namespace meta_hpp::detail { template < typename T > @@ -4707,6 +4788,11 @@ namespace meta_hpp::detail return nullptr; } + [[nodiscard]] inline const void* pointer_upcast(const void* ptr, const class_type& from, const class_type& to) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast) + return pointer_upcast(const_cast(ptr), from, to); + } + template < class_kind To, class_kind From > [[nodiscard]] To* pointer_upcast(From* ptr) { return static_cast(pointer_upcast(ptr, resolve_type(), resolve_type())); @@ -4714,8 +4800,7 @@ namespace meta_hpp::detail template < class_kind To, class_kind From > [[nodiscard]] const To* pointer_upcast(const From* ptr) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast) - return pointer_upcast(const_cast(ptr)); + return static_cast(pointer_upcast(ptr, resolve_type(), resolve_type())); } } @@ -8119,7 +8204,7 @@ namespace meta_hpp .deref = +[]([[maybe_unused]] const uvalue& v) -> uvalue { if constexpr ( detail::has_deref_traits ) { - return detail::deref_traits{}(v.cast()); + return detail::deref_traits{}(v.get_as_ref()); } else { detail::throw_exception_with("value type doesn't have value deref traits"); } @@ -8127,7 +8212,7 @@ namespace meta_hpp .index = +[]([[maybe_unused]] const uvalue& v, [[maybe_unused]] std::size_t i) -> uvalue { if constexpr ( detail::has_index_traits ) { - return detail::index_traits{}(v.cast(), i); + return detail::index_traits{}(v.get_as_ref(), i); } else { detail::throw_exception_with("value type doesn't have value index traits"); } @@ -8135,7 +8220,7 @@ namespace meta_hpp .less = +[]([[maybe_unused]] const uvalue& l, [[maybe_unused]] const uvalue& r) -> bool { if constexpr ( detail::has_less_traits ) { - return detail::less_traits{}(l.cast(), r.cast()); + return detail::less_traits{}(l.get_as_ref(), r.get_as_ref()); } else { detail::throw_exception_with("value type doesn't have value less traits"); } @@ -8143,7 +8228,7 @@ namespace meta_hpp .equals = +[]([[maybe_unused]] const uvalue& l, [[maybe_unused]] const uvalue& r) -> bool { if constexpr ( detail::has_equals_traits ) { - return detail::equals_traits{}(l.cast(), r.cast()); + return detail::equals_traits{}(l.get_as_ref(), r.get_as_ref()); } else { detail::throw_exception_with("value type doesn't have value equals traits"); } @@ -8151,7 +8236,7 @@ namespace meta_hpp .istream = +[]([[maybe_unused]] std::istream& is, [[maybe_unused]] uvalue& v) -> std::istream& { if constexpr ( detail::has_istream_traits ) { - return detail::istream_traits{}(is, v.cast()); + return detail::istream_traits{}(is, v.get_as_ref()); } else { detail::throw_exception_with("value type doesn't have value istream traits"); } @@ -8159,7 +8244,7 @@ namespace meta_hpp .ostream = +[]([[maybe_unused]] std::ostream& os, [[maybe_unused]] const uvalue& v) -> std::ostream& { if constexpr ( detail::has_ostream_traits ) { - return detail::ostream_traits{}(os, v.cast()); + return detail::ostream_traits{}(os, v.get_as_ref()); } else { detail::throw_exception_with("value type doesn't have value ostream traits"); } @@ -8260,55 +8345,216 @@ namespace meta_hpp } template < typename T > - std::decay_t& uvalue::cast() & { + T uvalue::get_as() & { + return meta_hpp::get_as(*this); + } + + template < typename T > + T uvalue::get_as() && { + return meta_hpp::get_as(std::move(*this)); + } + + template < typename T > + T uvalue::get_as() const & { + return meta_hpp::get_as(*this); + } + + template < typename T > + T uvalue::get_as() const && { + // NOLINTNEXTLINE(*-move-const-arg) + return meta_hpp::get_as(std::move(*this)); + } + + template < typename T > + T& uvalue::get_as_ref() & { + return meta_hpp::get_as_ref(*this); + } + + template < typename T > + T&& uvalue::get_as_ref() && { + return meta_hpp::get_as_ref(std::move(*this)); + } + + template < typename T > + const T& uvalue::get_as_ref() const & { + return meta_hpp::get_as_ref(*this); + } + + template < typename T > + const T&& uvalue::get_as_ref() const && { + // NOLINTNEXTLINE(*-move-const-arg) + return meta_hpp::get_as_ref(std::move(*this)); + } + + // + + template < typename T > + bool uvalue::can_get_as() & { + return meta_hpp::can_get_as(*this); + } + + template < typename T > + bool uvalue::can_get_as() && { + return meta_hpp::can_get_as(std::move(*this)); + } + + template < typename T > + bool uvalue::can_get_as() const & { + return meta_hpp::can_get_as(*this); + } + + template < typename T > + bool uvalue::can_get_as() const && { + // NOLINTNEXTLINE(*-move-const-arg) + return meta_hpp::can_get_as(std::move(*this)); + } + + template < typename T > + bool uvalue::can_get_as_ref() & { + return meta_hpp::can_get_as_ref(*this); + } + + template < typename T > + bool uvalue::can_get_as_ref() && { + return meta_hpp::can_get_as_ref(std::move(*this)); + } + + template < typename T > + bool uvalue::can_get_as_ref() const & { + return meta_hpp::can_get_as_ref(*this); + } + + template < typename T > + bool uvalue::can_get_as_ref() const && { + // NOLINTNEXTLINE(*-move-const-arg) + return meta_hpp::can_get_as_ref(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; - if ( Tp* ptr = try_cast() ) { - return *ptr; + static_assert(std::is_constructible_v>); + + const any_type& from_type = value.get_type(); + const any_type& to_type = resolve_type(); + + if ( from_type == to_type ) { + using to_ptr_t = detail::add_cv_t*; + auto to_ptr = static_cast(value.data()); + return static_cast(*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(); + + using to_ptr_t = detail::add_cv_t*; + auto to_ptr = static_cast(detail::pointer_upcast(value.data(), from_class, to_class)); + return static_cast(*to_ptr); + } + + if constexpr ( std::is_pointer_v ) { + if ( to_type.is_pointer() && from_type.is_nullptr() ) { + return static_cast(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 ) { + using from_data_ptr_t = detail::add_cv_t*; + auto from_data_ptr = static_cast(value.data()); + + if ( to_data_type.is_void() || to_data_type == from_data_type ) { + return static_cast(*from_data_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(to_ptr); + } + } + } + } + detail::throw_exception_with("bad value cast"); } - template < typename T > - std::decay_t&& uvalue::cast() && { + template < typename T, detail::decay_value_kind V > + [[nodiscard]] auto get_as_ref(V&& value) -> detail::add_cvref_t { + static_assert(!std::is_reference_v); + return get_as>(std::forward(value)); + } + + template < typename T, detail::decay_value_kind V > + [[nodiscard]] bool can_get_as(V&& value) noexcept { using Tp = std::decay_t; - if ( Tp* ptr = try_cast() ) { - return std::move(*ptr); + static_assert(std::is_constructible_v>); + + const any_type& from_type = value.get_type(); + const any_type& to_type = resolve_type(); + + if ( from_type == to_type ) { + return true; } - detail::throw_exception_with("bad value cast"); - } - template < typename T > - const std::decay_t& uvalue::cast() const & { - using Tp = std::decay_t; - if ( const Tp* ptr = try_cast() ) { - return *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) ) { + return true; } - detail::throw_exception_with("bad value cast"); - } - template < typename T > - const std::decay_t&& uvalue::cast() const && { - using Tp = std::decay_t; - if ( const Tp* ptr = try_cast() ) { - return std::move(*ptr); + if constexpr ( std::is_pointer_v ) { + if ( to_type.is_pointer() && from_type.is_nullptr() ) { + return true; + } + + 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 ) { + if ( to_data_type.is_void() || is_a(to_data_type, from_data_type) ) { + return true; + } + } + } } - detail::throw_exception_with("bad value cast"); + + return false; } - template < typename T > - std::decay_t* uvalue::try_cast() noexcept { - using Tp = std::decay_t; - return get_type() == resolve_type() - ? vtable_t::storage_cast(storage_) - : nullptr; - } - - template < typename T > - const std::decay_t* uvalue::try_cast() const noexcept { - using Tp = std::decay_t; - return get_type() == resolve_type() - ? vtable_t::storage_cast(storage_) - : nullptr; + template < typename T, detail::decay_value_kind V > + [[nodiscard]] bool can_get_as_ref(V&& value) noexcept { + static_assert(!std::is_reference_v); + return can_get_as>(std::forward(value)); } } @@ -8323,7 +8569,7 @@ namespace meta_hpp const any_type& l_type = l.get_type(); const any_type& r_type = resolve_type(); - return (l_type < r_type) || (l_type == r_type && l.cast() < r); + return (l_type < r_type) || (l_type == r_type && l.get_as_ref() < r); } template < typename T > @@ -8335,7 +8581,7 @@ namespace meta_hpp const any_type& l_type = resolve_type(); const any_type& r_type = r.get_type(); - return (l_type < r_type) || (l_type == r_type && l < r.cast()); + return (l_type < r_type) || (l_type == r_type && l < r.get_as_ref()); } [[nodiscard]] inline bool operator<(const uvalue& l, const uvalue& r) { @@ -8365,7 +8611,7 @@ namespace meta_hpp const any_type& l_type = l.get_type(); const any_type& r_type = resolve_type(); - return l_type == r_type && l.cast() == r; + return l_type == r_type && l.get_as_ref() == r; } template < typename T > @@ -8377,7 +8623,7 @@ namespace meta_hpp const any_type& l_type = resolve_type(); const any_type& r_type = r.get_type(); - return l_type == r_type && l == r.cast(); + return l_type == r_type && l == r.get_as_ref(); } [[nodiscard]] inline bool operator==(const uvalue& l, const uvalue& r) {