add value deref function

This commit is contained in:
BlackMATov
2022-01-15 07:48:22 +07:00
parent ef5b04add0
commit fb604ba61e
4 changed files with 126 additions and 11 deletions

20
TODO.md
View File

@@ -1,14 +1,16 @@
# meta.hpp # meta.hpp
- add type names; - add array value access
- add argument names - add return value policy
- add variable and member readonly flags
- add meta exception class; - add meta exception class;
- add conversion of nullptr to any pointers; - add conversion of nullptr to any pointers;
- add conversion of any pointers to void pointer ( identically cv-qualified ); - add conversion of any pointers to void pointer ( identically cv-qualified );
- add enum_type::create, number_type::create, and so on.
- add return value policy * argument names
- add is_invocable_with by dynamic types * argument defaults
- add metadata to every type and state * type conversions
- add integral implicit conversions * states and types metadata
- add meta::invoke function
? add type names;
? add enum_type::create, number_type::create, and so on.
? add invoke and is_invocable_with by dynamic types

View File

@@ -116,6 +116,11 @@ namespace meta_hpp::detail
namespace meta_hpp::detail namespace meta_hpp::detail
{ {
template < typename T >
concept has_deref_op_kind = requires(const T& v) {
{ *v } -> convertible_to<std::remove_pointer_t<T>>;
};
template < typename T > template < typename T >
concept has_less_op_kind = requires(const T& v) { concept has_less_op_kind = requires(const T& v) {
{ v < v } -> convertible_to<bool>; { v < v } -> convertible_to<bool>;
@@ -182,6 +187,10 @@ namespace meta_hpp
[[nodiscard]] const void* data() const noexcept; [[nodiscard]] const void* data() const noexcept;
[[nodiscard]] const void* cdata() const noexcept; [[nodiscard]] const void* cdata() const noexcept;
[[nodiscard]] value deref();
[[nodiscard]] value deref() const;
[[nodiscard]] value cderef() const;
template < typename T, typename Tp = std::decay_t<T> > template < typename T, typename Tp = std::decay_t<T> >
[[nodiscard]] Tp& cast() &; [[nodiscard]] Tp& cast() &;

View File

@@ -17,6 +17,9 @@ namespace meta_hpp
void* (*const data)(value&) noexcept; void* (*const data)(value&) noexcept;
const void* (*const cdata)(const value&) noexcept; const void* (*const cdata)(const value&) noexcept;
value (*const deref)(value&);
value (*const cderef)(const value&);
bool (*const less)(const value&, const value&); bool (*const less)(const value&, const value&);
bool (*const equals)(const value&, const value&); bool (*const equals)(const value&, const value&);
@@ -32,6 +35,8 @@ namespace meta_hpp
template < typename T > template < typename T >
const value::traits* value::traits::get() noexcept { const value::traits* value::traits::get() noexcept {
static_assert(std::is_same_v<T, std::decay_t<T>>);
static const traits traits{ static const traits traits{
.type = resolve_type<T>(), .type = resolve_type<T>(),
@@ -43,6 +48,22 @@ namespace meta_hpp
return v.try_cast<T>(); return v.try_cast<T>();
}, },
.deref = +[]([[maybe_unused]] value& v) -> value {
if constexpr ( detail::has_deref_op_kind<T> ) {
return value{*v.cast<T>()};
} else {
throw std::logic_error("value type doesn't have deref operator");
}
},
.cderef = +[]([[maybe_unused]] const value& v) -> value {
if constexpr ( detail::has_deref_op_kind<T> ) {
return value{*v.cast<T>()};
} else {
throw std::logic_error("value type doesn't have deref operator");
}
},
.less = +[]([[maybe_unused]] const value& l, [[maybe_unused]] const value& r) -> bool { .less = +[]([[maybe_unused]] const value& l, [[maybe_unused]] const value& r) -> bool {
if constexpr ( detail::has_less_op_kind<T> ) { if constexpr ( detail::has_less_op_kind<T> ) {
return l.cast<T>() < r.cast<T>(); return l.cast<T>() < r.cast<T>();
@@ -91,6 +112,7 @@ namespace meta_hpp
} }
}, },
}; };
return &traits; return &traits;
} }
} }
@@ -159,6 +181,18 @@ namespace meta_hpp
return traits_->cdata(*this); return traits_->cdata(*this);
} }
inline value value::deref() {
return traits_->deref(*this);
}
inline value value::deref() const {
return traits_->cderef(*this);
}
inline value value::cderef() const {
return traits_->cderef(*this);
}
template < typename T, typename Tp > template < typename T, typename Tp >
Tp& value::cast() & { Tp& value::cast() & {
if ( get_type() != resolve_type<Tp>() ) { if ( get_type() != resolve_type<Tp>() ) {

View File

@@ -30,6 +30,12 @@ namespace
++copy_ctor_counter; ++copy_ctor_counter;
} }
ivec2& add(const ivec2& other) {
x += other.x;
y += other.y;
return *this;
}
ivec2& operator=(ivec2&& other) = delete; ivec2& operator=(ivec2&& other) = delete;
ivec2& operator=(const ivec2& other) = delete; ivec2& operator=(const ivec2& other) = delete;
public: public:
@@ -344,21 +350,85 @@ TEST_CASE("meta/meta_utilities/value") {
CHECK_THROWS(std::ignore = operator==(meta::value{empty_class1{}}, meta::value{empty_class1{}})); CHECK_THROWS(std::ignore = operator==(meta::value{empty_class1{}}, meta::value{empty_class1{}}));
} }
} }
SUBCASE("deref") {
{
int i{42};
const meta::value v{meta::value{&i}.deref()};
CHECK(v.get_type() == meta::resolve_type<int>());
CHECK(v.data() != &i);
}
{
const char i{42};
const meta::value v{meta::value{&i}.deref()};
CHECK(v.get_type() == meta::resolve_type<char>());
CHECK(v.data() != &i);
}
{
const int i{42};
const int* const pi = &i;
const meta::value v{meta::value{&pi}.deref()};
CHECK(v.get_type() == meta::resolve_type<const int*>() );
CHECK(v.cast<const int*>() == pi);
}
{
int i{42};
void* p1 = &i;
const void* p2 = &i;
void* const& p3 = &i;
const void* const& p4 = &i;
CHECK_THROWS(std::ignore = meta::value(p1).deref());
CHECK_THROWS(std::ignore = meta::value(p2).deref());
CHECK_THROWS(std::ignore = meta::value(p3).deref());
CHECK_THROWS(std::ignore = meta::value(p4).deref());
}
{
ivec2 v{1,2};
meta::value vp{&v};
CHECK(ivec2::move_ctor_counter == 0);
CHECK(ivec2::copy_ctor_counter == 0);
meta::value vv1{vp.deref()};
CHECK(ivec2::move_ctor_counter == 0);
CHECK(ivec2::copy_ctor_counter == 1);
meta::value vv2{std::move(vp).deref()};
CHECK(ivec2::move_ctor_counter == 0);
CHECK(ivec2::copy_ctor_counter == 2);
meta::value vv3{vp.cderef()};
CHECK(ivec2::move_ctor_counter == 0);
CHECK(ivec2::copy_ctor_counter == 3);
}
}
} }
TEST_CASE("meta/meta_utilities/value/functions") { TEST_CASE("meta/meta_utilities/value/functions") {
namespace meta = meta_hpp; namespace meta = meta_hpp;
SUBCASE("add") {
{
const meta::value v{&ivec2::add};
CHECK(v.get_type() == meta::resolve_type<ivec2&(ivec2::*)(const ivec2&)>());
CHECK(std::invoke(v.cast<decltype(&ivec2::add)>(), ivec2{1,2}, ivec2{3,4}) == ivec2{4,6});
CHECK(std::invoke(*v.try_cast<decltype(&ivec2::add)>(), ivec2{1,2}, ivec2{3,4}) == ivec2{4,6});
}
}
SUBCASE("iadd2") { SUBCASE("iadd2") {
{ {
const meta::value v{iadd2}; const meta::value v{iadd2};
CHECK(v.get_type() == meta::resolve_type<ivec2(*)(ivec2, ivec2)>()); CHECK(v.get_type() == meta::resolve_type<ivec2(*)(ivec2, ivec2)>());
CHECK(v.cast<decltype(iadd2)>()(ivec2{1,2}, ivec2{3,4}) == ivec2{4,6}); CHECK(std::invoke(v.cast<decltype(iadd2)>(), ivec2{1,2}, ivec2{3,4}) == ivec2{4,6});
CHECK(std::invoke(*v.try_cast<decltype(iadd2)>(), ivec2{1,2}, ivec2{3,4}) == ivec2{4,6});
} }
{ {
const meta::value v{&iadd2}; const meta::value v{&iadd2};
CHECK(v.get_type() == meta::resolve_type<ivec2(*)(ivec2, ivec2)>()); CHECK(v.get_type() == meta::resolve_type<ivec2(*)(ivec2, ivec2)>());
CHECK(v.cast<decltype(&iadd2)>()(ivec2{1,2}, ivec2{3,4}) == ivec2{4,6}); CHECK(std::invoke(v.cast<decltype(&iadd2)>(), ivec2{1,2}, ivec2{3,4}) == ivec2{4,6});
CHECK(std::invoke(*v.try_cast<decltype(&iadd2)>(), ivec2{1,2}, ivec2{3,4}) == ivec2{4,6});
} }
} }
} }