new unmap uvalue operator

This commit is contained in:
BlackMATov
2023-01-18 03:29:29 +07:00
parent 702349dca9
commit cdbd078f02
5 changed files with 171 additions and 7 deletions

View File

@@ -2542,6 +2542,9 @@ namespace meta_hpp
[[nodiscard]] uvalue operator[](std::size_t index) const;
[[nodiscard]] bool has_index_op() const noexcept;
[[nodiscard]] uvalue unmap() const;
[[nodiscard]] bool has_unmap_op() const noexcept;
template < typename T >
[[nodiscard]] T get_as() &&;
@@ -8239,6 +8242,41 @@ namespace meta_hpp::detail
};
}
namespace meta_hpp::detail
{
template < typename T >
struct unmap_traits;
template < typename T >
concept has_unmap_traits = requires(const T& v) {
{ unmap_traits<T>{}(v) } -> std::convertible_to<uvalue>;
};
}
namespace meta_hpp::detail
{
template < typename T >
struct unmap_traits<std::shared_ptr<T>> {
uvalue operator()(const std::shared_ptr<T>& v) const {
return uvalue{v.get()};
}
};
template < typename T, typename D >
struct unmap_traits<std::unique_ptr<T, D>> {
uvalue operator()(const std::unique_ptr<T, D>& v) const {
return uvalue{v.get()};
}
};
template < typename T >
struct unmap_traits<std::reference_wrapper<T>> {
uvalue operator()(const std::reference_wrapper<T>& v) const {
return uvalue{std::addressof(v.get())};
}
};
}
namespace meta_hpp
{
struct uvalue::vtable_t final {
@@ -8253,6 +8291,7 @@ namespace meta_hpp
uvalue (*const deref)(const storage_u& from);
uvalue (*const index)(const storage_u& from, std::size_t);
uvalue (*const unmap)(const storage_u& from);
template < typename T >
static T* buffer_cast(buffer_t& buffer) noexcept {
@@ -8404,7 +8443,6 @@ namespace meta_hpp
self.vtable_ = nullptr;
},
.deref = [](){
if constexpr ( detail::has_deref_traits<Tp> ) {
return +[](const storage_u& from) -> uvalue {
@@ -8424,6 +8462,16 @@ namespace meta_hpp
return nullptr;
}
}(),
.unmap = [](){
if constexpr ( detail::has_unmap_traits<Tp> ) {
return +[](const storage_u& from) -> uvalue {
return detail::unmap_traits<Tp>{}(*storage_cast<Tp>(from));
};
} else {
return nullptr;
}
}(),
};
return &table;
@@ -8562,6 +8610,14 @@ namespace meta_hpp
return vtable_ != nullptr && vtable_->index != nullptr;
}
inline uvalue uvalue::unmap() const {
return has_unmap_op() ? vtable_->unmap(storage_) : uvalue{};
}
inline bool uvalue::has_unmap_op() const noexcept {
return vtable_ != nullptr && vtable_->unmap != nullptr;
}
template < typename T >
T uvalue::get_as() && {
static_assert(std::is_same_v<T, std::decay_t<T>>);

View File

@@ -382,6 +382,50 @@ TEST_CASE("meta/meta_utilities/value") {
CHECK(val2.get_as<ivec2>() == ivec2{1,2});
}
SUBCASE("unmap") {
{
const meta::uvalue u{42};
CHECK_FALSE(u.has_unmap_op());
CHECK_FALSE(u.unmap());
}
{
int i{42};
const meta::uvalue u{std::ref(i)};
CHECK(u.has_unmap_op());
const meta::uvalue v{u.unmap()};
CHECK(v.get_type() == meta::resolve_type<int*>());
CHECK(v.get_as<int*>() == &i);
}
{
const int i{42};
const meta::uvalue u{std::ref(i)};
CHECK(u.has_unmap_op());
const meta::uvalue v{u.unmap()};
CHECK(v.get_type() == meta::resolve_type<const int*>());
CHECK(v.get_as<const int*>() == &i);
}
{
const auto i = std::make_shared<ivec2>(3, 4);
const meta::uvalue u{i};
CHECK(u.has_unmap_op());
const meta::uvalue v{u.unmap()};
CHECK(v.get_type() == meta::resolve_type<ivec2*>());
CHECK(v.get_as<ivec2*>() == i.get());
}
{
const auto i = std::make_shared<const ivec2>(3, 4);
const meta::uvalue u{i};
CHECK(u.has_unmap_op());
const meta::uvalue v{u.unmap()};
CHECK(v.get_type() == meta::resolve_type<const ivec2*>());
CHECK(v.get_as<const ivec2*>() == i.get());
}
}
SUBCASE("deref") {
{
int i{42};
@@ -389,8 +433,7 @@ TEST_CASE("meta/meta_utilities/value") {
CHECK(u.has_deref_op());
const meta::uvalue v{*u};
CHECK(v.get_type() == meta::resolve_type<int>());
CHECK(v.get_data() != &i);
CHECK(v.get_as<int>() == i);
}
{
const char i{42};
@@ -398,8 +441,7 @@ TEST_CASE("meta/meta_utilities/value") {
CHECK(u.has_deref_op());
const meta::uvalue v{*u};
CHECK(v.get_type() == meta::resolve_type<char>());
CHECK(v.get_data() != &i);
CHECK(v.get_as<char>() == i);
}
{
const int i{42};
@@ -408,7 +450,6 @@ TEST_CASE("meta/meta_utilities/value") {
CHECK(u.has_deref_op());
const meta::uvalue v{*u};
CHECK(v.get_type() == meta::resolve_type<const int*>() );
CHECK(v.get_as<const int*>() == pi);
}
{

View File

@@ -0,0 +1,45 @@
/*******************************************************************************
* 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)
******************************************************************************/
#pragma once
#include "../../meta_base.hpp"
#include "../../meta_uvalue.hpp"
namespace meta_hpp::detail
{
template < typename T >
struct unmap_traits;
template < typename T >
concept has_unmap_traits = requires(const T& v) {
{ unmap_traits<T>{}(v) } -> std::convertible_to<uvalue>;
};
}
namespace meta_hpp::detail
{
template < typename T >
struct unmap_traits<std::shared_ptr<T>> {
uvalue operator()(const std::shared_ptr<T>& v) const {
return uvalue{v.get()};
}
};
template < typename T, typename D >
struct unmap_traits<std::unique_ptr<T, D>> {
uvalue operator()(const std::unique_ptr<T, D>& v) const {
return uvalue{v.get()};
}
};
template < typename T >
struct unmap_traits<std::reference_wrapper<T>> {
uvalue operator()(const std::reference_wrapper<T>& v) const {
return uvalue{std::addressof(v.get())};
}
};
}

View File

@@ -88,6 +88,9 @@ namespace meta_hpp
[[nodiscard]] uvalue operator[](std::size_t index) const;
[[nodiscard]] bool has_index_op() const noexcept;
[[nodiscard]] uvalue unmap() const;
[[nodiscard]] bool has_unmap_op() const noexcept;
template < typename T >
[[nodiscard]] T get_as() &&;

View File

@@ -12,6 +12,7 @@
#include "../meta_detail/value_traits/deref_traits.hpp"
#include "../meta_detail/value_traits/index_traits.hpp"
#include "../meta_detail/value_traits/unmap_traits.hpp"
#include "../meta_detail/value_utilities/utraits.hpp"
@@ -29,6 +30,7 @@ namespace meta_hpp
uvalue (*const deref)(const storage_u& from);
uvalue (*const index)(const storage_u& from, std::size_t);
uvalue (*const unmap)(const storage_u& from);
template < typename T >
static T* buffer_cast(buffer_t& buffer) noexcept {
@@ -180,7 +182,6 @@ namespace meta_hpp
self.vtable_ = nullptr;
},
.deref = [](){
if constexpr ( detail::has_deref_traits<Tp> ) {
return +[](const storage_u& from) -> uvalue {
@@ -200,6 +201,16 @@ namespace meta_hpp
return nullptr;
}
}(),
.unmap = [](){
if constexpr ( detail::has_unmap_traits<Tp> ) {
return +[](const storage_u& from) -> uvalue {
return detail::unmap_traits<Tp>{}(*storage_cast<Tp>(from));
};
} else {
return nullptr;
}
}(),
};
return &table;
@@ -338,6 +349,14 @@ namespace meta_hpp
return vtable_ != nullptr && vtable_->index != nullptr;
}
inline uvalue uvalue::unmap() const {
return has_unmap_op() ? vtable_->unmap(storage_) : uvalue{};
}
inline bool uvalue::has_unmap_op() const noexcept {
return vtable_ != nullptr && vtable_->unmap != nullptr;
}
template < typename T >
T uvalue::get_as() && {
static_assert(std::is_same_v<T, std::decay_t<T>>);