diff --git a/develop/singles/headers/meta.hpp/meta_all.hpp b/develop/singles/headers/meta.hpp/meta_all.hpp index a0e2c2d..0d9dc23 100644 --- a/develop/singles/headers/meta.hpp/meta_all.hpp +++ b/develop/singles/headers/meta.hpp/meta_all.hpp @@ -2366,11 +2366,14 @@ namespace meta_hpp [[nodiscard]] uvalue operator[](std::size_t index) const; template < typename T > - [[nodiscard]] auto get_as() + [[nodiscard]] T get_as() &&; + + template < typename T > + [[nodiscard]] auto get_as() & -> std::conditional_t, T, T&>; template < typename T > - [[nodiscard]] auto get_as() const + [[nodiscard]] auto get_as() const & -> std::conditional_t, T, const T&>; template < typename T > @@ -5635,7 +5638,7 @@ namespace meta_hpp } for ( auto&& [_, evalue] : data_->evalues ) { - if ( evalue.get_value().get_as() == value ) { + if ( evalue.get_value().template get_as() == value ) { return evalue.get_index().get_name(); } } @@ -8388,7 +8391,24 @@ namespace meta_hpp } template < typename T > - auto uvalue::get_as() -> std::conditional_t, T, T&> { + [[nodiscard]] T uvalue::get_as() && { + static_assert(std::is_same_v>); + + if constexpr ( detail::pointer_kind ) { + if ( T ptr = try_get_as(); ptr || get_type().is_nullptr() ) { + return ptr; + } + } else { + if ( T* ptr = try_get_as() ) { + return std::move(*ptr); + } + } + + detail::throw_exception_with("bad value cast"); + } + + template < typename T > + auto uvalue::get_as() & -> std::conditional_t, T, T&> { static_assert(std::is_same_v>); if constexpr ( detail::pointer_kind ) { @@ -8405,7 +8425,7 @@ namespace meta_hpp } template < typename T > - auto uvalue::get_as() const -> std::conditional_t, T, const T&> { + auto uvalue::get_as() const & -> std::conditional_t, T, const T&> { static_assert(std::is_same_v>); if constexpr ( detail::pointer_kind ) { diff --git a/develop/untests/meta_utilities/value3_tests.cpp b/develop/untests/meta_utilities/value3_tests.cpp index 3665af4..34d61e8 100644 --- a/develop/untests/meta_utilities/value3_tests.cpp +++ b/develop/untests/meta_utilities/value3_tests.cpp @@ -91,7 +91,7 @@ TEST_CASE("meta/meta_utilities/value4/get_as") { namespace meta = meta_hpp; static_assert(std::is_same_v().get_as()), derived&>); - static_assert(std::is_same_v().get_as()), derived&>); + static_assert(std::is_same_v().get_as()), derived>); static_assert(std::is_same_v().get_as()), const derived&>); static_assert(std::is_same_v().get_as()), const derived&>); diff --git a/develop/untests/meta_utilities/value_tests.cpp b/develop/untests/meta_utilities/value_tests.cpp index ffef9c8..b620385 100644 --- a/develop/untests/meta_utilities/value_tests.cpp +++ b/develop/untests/meta_utilities/value_tests.cpp @@ -111,7 +111,7 @@ TEST_CASE("meta/meta_utilities/value") { ivec2&>); static_assert(std::is_same_v< decltype(std::declval().get_as()), - ivec2&>); + ivec2>); static_assert(std::is_same_v< decltype(std::declval().get_as()), const ivec2&>); @@ -166,8 +166,15 @@ TEST_CASE("meta/meta_utilities/value") { CHECK(val.get_as() == ivec2{1,2}); CHECK(std::as_const(val).get_as() == ivec2{1,2}); - CHECK(std::move(val).get_as() == ivec2{1,2}); - CHECK(std::move(std::as_const(val)).get_as() == ivec2{1,2}); + + { + meta::uvalue val_copy{val}; + CHECK(std::move(val_copy).get_as() == ivec2{1,2}); + } + { + meta::uvalue val_copy{val}; + CHECK(std::move(std::as_const(val_copy)).get_as() == ivec2{1,2}); + } CHECK_THROWS(std::ignore = val.get_as()); CHECK_THROWS(std::ignore = std::as_const(val).get_as()); @@ -199,8 +206,15 @@ TEST_CASE("meta/meta_utilities/value") { CHECK(val.get_as() == ivec2{1,2}); CHECK(std::as_const(val).get_as() == ivec2{1,2}); - CHECK(std::move(val).get_as() == ivec2{1,2}); - CHECK(std::move(std::as_const(val)).get_as() == ivec2{1,2}); + + { + meta::uvalue val_copy{val}; + CHECK(std::move(val_copy).get_as() == ivec2{1,2}); + } + { + meta::uvalue val_copy{val}; + CHECK(std::move(std::as_const(val_copy)).get_as() == ivec2{1,2}); + } CHECK_THROWS(std::ignore = val.get_as()); CHECK_THROWS(std::ignore = std::as_const(val).get_as()); @@ -226,8 +240,15 @@ TEST_CASE("meta/meta_utilities/value") { CHECK(val.get_as() == ivec2{1,2}); CHECK(std::as_const(val).get_as() == ivec2{1,2}); - CHECK(std::move(val).get_as() == ivec2{1,2}); - CHECK(std::move(std::as_const(val)).get_as() == ivec2{1,2}); + + { + meta::uvalue val_copy{val}; + CHECK(std::move(val_copy).get_as() == ivec2{1,2}); + } + { + meta::uvalue val_copy{val}; + CHECK(std::move(std::as_const(val_copy)).get_as() == ivec2{1,2}); + } CHECK_THROWS(std::ignore = val.get_as()); CHECK_THROWS(std::ignore = std::as_const(val).get_as()); @@ -253,8 +274,15 @@ TEST_CASE("meta/meta_utilities/value") { CHECK(val.get_as() == ivec2{1,2}); CHECK(std::as_const(val).get_as() == ivec2{1,2}); - CHECK(std::move(val).get_as() == ivec2{1,2}); - CHECK(std::move(std::as_const(val)).get_as() == ivec2{1,2}); + + { + meta::uvalue val_copy{val}; + CHECK(std::move(val_copy).get_as() == ivec2{1,2}); + } + { + meta::uvalue val_copy{val}; + CHECK(std::move(std::as_const(val_copy)).get_as() == ivec2{1,2}); + } CHECK_THROWS(std::ignore = val.get_as()); CHECK_THROWS(std::ignore = std::as_const(val).get_as()); diff --git a/headers/meta.hpp/meta_types/enum_type.hpp b/headers/meta.hpp/meta_types/enum_type.hpp index 42ff81b..0e72405 100644 --- a/headers/meta.hpp/meta_types/enum_type.hpp +++ b/headers/meta.hpp/meta_types/enum_type.hpp @@ -76,7 +76,7 @@ namespace meta_hpp } for ( auto&& [_, evalue] : data_->evalues ) { - if ( evalue.get_value().get_as() == value ) { + if ( evalue.get_value().template get_as() == value ) { return evalue.get_index().get_name(); } } diff --git a/headers/meta.hpp/meta_uvalue.hpp b/headers/meta.hpp/meta_uvalue.hpp index fc199f3..988f9a3 100644 --- a/headers/meta.hpp/meta_uvalue.hpp +++ b/headers/meta.hpp/meta_uvalue.hpp @@ -86,11 +86,14 @@ namespace meta_hpp [[nodiscard]] uvalue operator[](std::size_t index) const; template < typename T > - [[nodiscard]] auto get_as() + [[nodiscard]] T get_as() &&; + + template < typename T > + [[nodiscard]] auto get_as() & -> std::conditional_t, T, T&>; template < typename T > - [[nodiscard]] auto get_as() const + [[nodiscard]] auto get_as() const & -> std::conditional_t, T, const T&>; template < typename T > diff --git a/headers/meta.hpp/meta_uvalue/uvalue.hpp b/headers/meta.hpp/meta_uvalue/uvalue.hpp index 9b283a1..78f071b 100644 --- a/headers/meta.hpp/meta_uvalue/uvalue.hpp +++ b/headers/meta.hpp/meta_uvalue/uvalue.hpp @@ -326,7 +326,24 @@ namespace meta_hpp } template < typename T > - auto uvalue::get_as() -> std::conditional_t, T, T&> { + [[nodiscard]] T uvalue::get_as() && { + static_assert(std::is_same_v>); + + if constexpr ( detail::pointer_kind ) { + if ( T ptr = try_get_as(); ptr || get_type().is_nullptr() ) { + return ptr; + } + } else { + if ( T* ptr = try_get_as() ) { + return std::move(*ptr); + } + } + + detail::throw_exception_with("bad value cast"); + } + + template < typename T > + auto uvalue::get_as() & -> std::conditional_t, T, T&> { static_assert(std::is_same_v>); if constexpr ( detail::pointer_kind ) { @@ -343,7 +360,7 @@ namespace meta_hpp } template < typename T > - auto uvalue::get_as() const -> std::conditional_t, T, const T&> { + auto uvalue::get_as() const & -> std::conditional_t, T, const T&> { static_assert(std::is_same_v>); if constexpr ( detail::pointer_kind ) {