mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-15 03:45:30 +07:00
new uvalue safe api
This commit is contained in:
@@ -20,6 +20,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -2857,6 +2858,15 @@ namespace meta_hpp
|
|||||||
[[nodiscard]] auto try_get_as() const noexcept //
|
[[nodiscard]] auto try_get_as() const noexcept //
|
||||||
-> std::conditional_t<detail::pointer_kind<T>, T, const T*>;
|
-> 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:
|
private:
|
||||||
struct vtable_t;
|
struct vtable_t;
|
||||||
|
|
||||||
@@ -8647,4 +8657,55 @@ namespace meta_hpp
|
|||||||
|
|
||||||
return nullptr;
|
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;
|
namespace meta = meta_hpp;
|
||||||
|
|
||||||
meta::class_<base0>();
|
meta::class_<base0>();
|
||||||
@@ -50,7 +50,7 @@ TEST_CASE("meta/meta_utilities/value4") {
|
|||||||
.base_<base2>();
|
.base_<base2>();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("meta/meta_utilities/value4/get_type") {
|
TEST_CASE("meta/meta_utilities/value3/get_type") {
|
||||||
namespace meta = meta_hpp;
|
namespace meta = meta_hpp;
|
||||||
|
|
||||||
SUBCASE("from ref") {
|
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;
|
namespace meta = meta_hpp;
|
||||||
|
|
||||||
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&>().get_as<derived>()), derived&>);
|
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;
|
namespace meta = meta_hpp;
|
||||||
|
|
||||||
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&>().try_get_as<derived>()), derived*>);
|
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;
|
namespace meta = meta_hpp;
|
||||||
|
|
||||||
meta::class_<clazz_throw_dtor>()
|
meta::class_<clazz_throw_dtor>()
|
||||||
.function_("make", &clazz_throw_dtor::make);
|
.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;
|
namespace meta = meta_hpp;
|
||||||
|
|
||||||
SUBCASE("value") {
|
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;
|
namespace meta = meta_hpp;
|
||||||
|
|
||||||
clazz_throw_dtor::destructor_counter = 0;
|
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;
|
namespace meta = meta_hpp;
|
||||||
|
|
||||||
clazz_throw_dtor::destructor_counter = 0;
|
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 <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
@@ -110,6 +110,15 @@ namespace meta_hpp
|
|||||||
[[nodiscard]] auto try_get_as() const noexcept //
|
[[nodiscard]] auto try_get_as() const noexcept //
|
||||||
-> std::conditional_t<detail::pointer_kind<T>, T, const T*>;
|
-> 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:
|
private:
|
||||||
struct vtable_t;
|
struct vtable_t;
|
||||||
|
|
||||||
|
|||||||
@@ -619,4 +619,55 @@ namespace meta_hpp
|
|||||||
|
|
||||||
return nullptr;
|
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