mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-13 19:18:01 +07:00
new uvalue safe api
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <span>
|
||||
#include <string>
|
||||
@@ -2857,6 +2858,15 @@ namespace meta_hpp
|
||||
[[nodiscard]] auto try_get_as() const noexcept //
|
||||
-> std::conditional_t<detail::pointer_kind<T>, T, const T*>;
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::optional<T> safe_get_as() &&;
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::optional<T> safe_get_as() &;
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::optional<T> safe_get_as() const&;
|
||||
|
||||
private:
|
||||
struct vtable_t;
|
||||
|
||||
@@ -8647,4 +8657,55 @@ namespace meta_hpp
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
std::optional<T> uvalue::safe_get_as() && {
|
||||
static_assert(std::is_same_v<T, std::decay_t<T>>);
|
||||
|
||||
if constexpr ( detail::pointer_kind<T> ) {
|
||||
if ( T ptr = try_get_as<T>(); ptr || get_type().is_nullptr() ) {
|
||||
return ptr;
|
||||
}
|
||||
} else {
|
||||
if ( T* ptr = try_get_as<T>() ) {
|
||||
return std::move(*ptr);
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
std::optional<T> uvalue::safe_get_as() & {
|
||||
static_assert(std::is_same_v<T, std::decay_t<T>>);
|
||||
|
||||
if constexpr ( detail::pointer_kind<T> ) {
|
||||
if ( T ptr = try_get_as<T>(); ptr || get_type().is_nullptr() ) {
|
||||
return ptr;
|
||||
}
|
||||
} else {
|
||||
if ( T* ptr = try_get_as<T>() ) {
|
||||
return *ptr;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
std::optional<T> uvalue::safe_get_as() const& {
|
||||
static_assert(std::is_same_v<T, std::decay_t<T>>);
|
||||
|
||||
if constexpr ( detail::pointer_kind<T> ) {
|
||||
if ( T ptr = try_get_as<T>(); ptr || get_type().is_nullptr() ) {
|
||||
return ptr;
|
||||
}
|
||||
} else {
|
||||
if ( const T* ptr = try_get_as<T>() ) {
|
||||
return *ptr;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_utilities/value4") {
|
||||
TEST_CASE("meta/meta_utilities/value3") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
meta::class_<base0>();
|
||||
@@ -50,7 +50,7 @@ TEST_CASE("meta/meta_utilities/value4") {
|
||||
.base_<base2>();
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_utilities/value4/get_type") {
|
||||
TEST_CASE("meta/meta_utilities/value3/get_type") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
SUBCASE("from ref") {
|
||||
@@ -88,7 +88,7 @@ TEST_CASE("meta/meta_utilities/value4/get_type") {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_utilities/value4/get_as") {
|
||||
TEST_CASE("meta/meta_utilities/value3/get_as") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&>().get_as<derived>()), derived&>);
|
||||
@@ -207,7 +207,7 @@ TEST_CASE("meta/meta_utilities/value4/get_as") {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_utilities/value4/try_get_as") {
|
||||
TEST_CASE("meta/meta_utilities/value3/try_get_as") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&>().try_get_as<derived>()), derived*>);
|
||||
|
||||
@@ -46,14 +46,14 @@ namespace
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_utilities/value5") {
|
||||
TEST_CASE("meta/meta_utilities/value4") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
meta::class_<clazz_throw_dtor>()
|
||||
.function_("make", &clazz_throw_dtor::make);
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_utilities/value5/throw_dtor") {
|
||||
TEST_CASE("meta/meta_utilities/value4/throw_dtor") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
SUBCASE("value") {
|
||||
@@ -97,7 +97,7 @@ TEST_CASE("meta/meta_utilities/value5/throw_dtor") {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_utilities/value5/inplace") {
|
||||
TEST_CASE("meta/meta_utilities/value4/inplace") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
clazz_throw_dtor::destructor_counter = 0;
|
||||
@@ -174,7 +174,7 @@ TEST_CASE("meta/meta_utilities/value5/inplace") {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_utilities/value5/emplace") {
|
||||
TEST_CASE("meta/meta_utilities/value4/emplace") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
clazz_throw_dtor::destructor_counter = 0;
|
||||
|
||||
169
develop/untests/meta_utilities/value5_tests.cpp
Normal file
169
develop/untests/meta_utilities/value5_tests.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021-2023, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include <meta.hpp/meta_all.hpp>
|
||||
#include <doctest/doctest.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
struct ivec2 final {
|
||||
int x{};
|
||||
int y{};
|
||||
|
||||
ivec2(int nx, int ny)
|
||||
: x{nx}, y{ny} {}
|
||||
|
||||
ivec2(ivec2&& other) noexcept
|
||||
: x{other.x}
|
||||
, y{other.y} {
|
||||
other.x = 0;
|
||||
other.y = 0;
|
||||
}
|
||||
|
||||
ivec2(const ivec2& other)
|
||||
: x{other.x}
|
||||
, y{other.y} {}
|
||||
};
|
||||
|
||||
bool operator==(const ivec2& l, const ivec2& r) noexcept {
|
||||
return l.x == r.x && l.y == r.y;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_utilities/value5/safe_get_as") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
SUBCASE("&/val") {
|
||||
{
|
||||
meta::uvalue v{ivec2{1,2}};
|
||||
|
||||
REQUIRE(v.safe_get_as<ivec2>());
|
||||
CHECK(v.safe_get_as<ivec2>() == ivec2{1,2});
|
||||
|
||||
CHECK_FALSE(v.safe_get_as<int>());
|
||||
}
|
||||
{
|
||||
const meta::uvalue v{ivec2{1,2}};
|
||||
|
||||
REQUIRE(v.safe_get_as<ivec2>());
|
||||
CHECK(v.safe_get_as<ivec2>() == ivec2{1,2});
|
||||
|
||||
CHECK_FALSE(v.safe_get_as<int>());
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("&&/val") {
|
||||
{
|
||||
meta::uvalue v{ivec2{1,2}};
|
||||
const ivec2 v2 = *std::move(v).safe_get_as<ivec2>();
|
||||
CHECK(v2 == ivec2{1,2});
|
||||
CHECK(v.get_as<ivec2>() == ivec2{0,0});
|
||||
}
|
||||
{
|
||||
meta::uvalue v{ivec2{1,2}};
|
||||
CHECK_FALSE(std::move(v).safe_get_as<int>());
|
||||
CHECK(v.get_as<ivec2>() == ivec2{1,2});
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("&/ptr") {
|
||||
{
|
||||
ivec2 v{1,2};
|
||||
meta::uvalue v2{&v};
|
||||
|
||||
REQUIRE(v2.safe_get_as<ivec2*>());
|
||||
REQUIRE(*v2.safe_get_as<ivec2*>());
|
||||
CHECK(*v2.safe_get_as<ivec2*>() == &v);
|
||||
|
||||
REQUIRE(v2.safe_get_as<const ivec2*>());
|
||||
REQUIRE(*v2.safe_get_as<const ivec2*>());
|
||||
CHECK(*v2.safe_get_as<const ivec2*>() == &v);
|
||||
|
||||
CHECK_FALSE(v2.safe_get_as<ivec2>());
|
||||
CHECK_FALSE(v2.safe_get_as<int*>());
|
||||
CHECK_FALSE(v2.safe_get_as<const int*>());
|
||||
}
|
||||
{
|
||||
ivec2 v{1,2};
|
||||
const meta::uvalue v2{&v};
|
||||
|
||||
REQUIRE(v2.safe_get_as<ivec2*>());
|
||||
REQUIRE(*v2.safe_get_as<ivec2*>());
|
||||
CHECK(*v2.safe_get_as<ivec2*>() == &v);
|
||||
|
||||
REQUIRE(v2.safe_get_as<const ivec2*>());
|
||||
REQUIRE(*v2.safe_get_as<const ivec2*>());
|
||||
CHECK(*v2.safe_get_as<const ivec2*>() == &v);
|
||||
|
||||
CHECK_FALSE(v2.safe_get_as<ivec2>());
|
||||
CHECK_FALSE(v2.safe_get_as<int*>());
|
||||
CHECK_FALSE(v2.safe_get_as<const int*>());
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("&/const_ptr") {
|
||||
{
|
||||
const ivec2 v{1,2};
|
||||
meta::uvalue v2{&v};
|
||||
|
||||
CHECK_FALSE(v2.safe_get_as<ivec2*>());
|
||||
|
||||
REQUIRE(v2.safe_get_as<const ivec2*>());
|
||||
REQUIRE(*v2.safe_get_as<const ivec2*>());
|
||||
CHECK(*v2.safe_get_as<const ivec2*>() == &v);
|
||||
|
||||
CHECK_FALSE(v2.safe_get_as<ivec2>());
|
||||
CHECK_FALSE(v2.safe_get_as<int*>());
|
||||
CHECK_FALSE(v2.safe_get_as<const int*>());
|
||||
}
|
||||
{
|
||||
const ivec2 v{1,2};
|
||||
const meta::uvalue v2{&v};
|
||||
|
||||
CHECK_FALSE(v2.safe_get_as<ivec2*>());
|
||||
|
||||
REQUIRE(v2.safe_get_as<const ivec2*>());
|
||||
REQUIRE(*v2.safe_get_as<const ivec2*>());
|
||||
CHECK(*v2.safe_get_as<const ivec2*>() == &v);
|
||||
|
||||
CHECK_FALSE(v2.safe_get_as<ivec2>());
|
||||
CHECK_FALSE(v2.safe_get_as<int*>());
|
||||
CHECK_FALSE(v2.safe_get_as<const int*>());
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("&&/ptr") {
|
||||
{
|
||||
ivec2 v{1,2};
|
||||
meta::uvalue v2{&v};
|
||||
REQUIRE(std::move(v2).safe_get_as<ivec2*>());
|
||||
CHECK(*std::move(v2).safe_get_as<ivec2*>() == &v);
|
||||
}
|
||||
{
|
||||
ivec2 v{1,2};
|
||||
const meta::uvalue v2{&v};
|
||||
REQUIRE(std::move(v2).safe_get_as<ivec2*>());
|
||||
CHECK(*std::move(v2).safe_get_as<ivec2*>() == &v);
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("&&/const ptr") {
|
||||
{
|
||||
const ivec2 v{1,2};
|
||||
meta::uvalue v2{&v};
|
||||
CHECK_FALSE(std::move(v2).safe_get_as<ivec2*>());
|
||||
REQUIRE(std::move(v2).safe_get_as<const ivec2*>());
|
||||
CHECK(*std::move(v2).safe_get_as<const ivec2*>() == &v);
|
||||
}
|
||||
{
|
||||
const ivec2 v{1,2};
|
||||
const meta::uvalue v2{&v};
|
||||
CHECK_FALSE(std::move(v2).safe_get_as<ivec2*>());
|
||||
REQUIRE(std::move(v2).safe_get_as<const ivec2*>());
|
||||
CHECK(*std::move(v2).safe_get_as<const ivec2*>() == &v);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <span>
|
||||
#include <string>
|
||||
|
||||
@@ -110,6 +110,15 @@ namespace meta_hpp
|
||||
[[nodiscard]] auto try_get_as() const noexcept //
|
||||
-> std::conditional_t<detail::pointer_kind<T>, T, const T*>;
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::optional<T> safe_get_as() &&;
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::optional<T> safe_get_as() &;
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] std::optional<T> safe_get_as() const&;
|
||||
|
||||
private:
|
||||
struct vtable_t;
|
||||
|
||||
|
||||
@@ -619,4 +619,55 @@ namespace meta_hpp
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
std::optional<T> uvalue::safe_get_as() && {
|
||||
static_assert(std::is_same_v<T, std::decay_t<T>>);
|
||||
|
||||
if constexpr ( detail::pointer_kind<T> ) {
|
||||
if ( T ptr = try_get_as<T>(); ptr || get_type().is_nullptr() ) {
|
||||
return ptr;
|
||||
}
|
||||
} else {
|
||||
if ( T* ptr = try_get_as<T>() ) {
|
||||
return std::move(*ptr);
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
std::optional<T> uvalue::safe_get_as() & {
|
||||
static_assert(std::is_same_v<T, std::decay_t<T>>);
|
||||
|
||||
if constexpr ( detail::pointer_kind<T> ) {
|
||||
if ( T ptr = try_get_as<T>(); ptr || get_type().is_nullptr() ) {
|
||||
return ptr;
|
||||
}
|
||||
} else {
|
||||
if ( T* ptr = try_get_as<T>() ) {
|
||||
return *ptr;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
std::optional<T> uvalue::safe_get_as() const& {
|
||||
static_assert(std::is_same_v<T, std::decay_t<T>>);
|
||||
|
||||
if constexpr ( detail::pointer_kind<T> ) {
|
||||
if ( T ptr = try_get_as<T>(); ptr || get_type().is_nullptr() ) {
|
||||
return ptr;
|
||||
}
|
||||
} else {
|
||||
if ( const T* ptr = try_get_as<T>() ) {
|
||||
return *ptr;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user