Skip to content

Commit

Permalink
new uvalue's size_traits
Browse files Browse the repository at this point in the history
discussion: #114
  • Loading branch information
BlackMATov committed Jan 23, 2025
1 parent 107c476 commit 166e6f3
Show file tree
Hide file tree
Showing 7 changed files with 261 additions and 22 deletions.
118 changes: 107 additions & 11 deletions develop/singles/headers/meta.hpp/meta_all.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <exception>
#include <functional>
#include <initializer_list>
#include <iterator>
#include <map>
#include <memory>
#include <mutex>
Expand Down Expand Up @@ -2756,6 +2757,9 @@ namespace meta_hpp
[[nodiscard]] uvalue unmap() const;
[[nodiscard]] bool has_unmap_op() const noexcept;

[[nodiscard]] std::size_t size() const;
[[nodiscard]] bool has_size_op() const noexcept;

[[nodiscard]] bool less(const uvalue& other) const;
[[nodiscard]] bool has_less_op() const noexcept;

Expand Down Expand Up @@ -11280,6 +11284,71 @@ namespace meta_hpp::detail
}; \
}

namespace meta_hpp::detail
{
template < typename T >
struct size_traits;

template < typename T >
concept has_size_traits //
= requires(const T& v) { size_traits<std::remove_cv_t<T>>{}(v); };
}

namespace meta_hpp::detail
{
template < typename T, std::size_t Size >
struct size_traits<std::array<T, Size>> {
std::size_t operator()(const std::array<T, Size>& v) const {
using std::size;
return size(v);
}
};

template < typename T, typename Traits, typename Allocator >
struct size_traits<std::basic_string<T, Traits, Allocator>> {
std::size_t operator()(const std::basic_string<T, Traits, Allocator>& v) const {
using std::size;
return size(v);
}
};

template < typename T, typename Traits >
struct size_traits<std::basic_string_view<T, Traits>> {
std::size_t operator()(const std::basic_string_view<T, Traits>& v) const {
using std::size;
return size(v);
}
};

template < typename T, std::size_t Extent >
struct size_traits<std::span<T, Extent>> {
std::size_t operator()(const std::span<T, Extent>& v) const {
using std::size;
return size(v);
}
};

template < typename T, typename Allocator >
struct size_traits<std::vector<T, Allocator>> {
std::size_t operator()(const std::vector<T, Allocator>& v) const {
using std::size;
return size(v);
}
};
}

#define META_HPP_DECLARE_SIZE_TRAITS_FOR(T) \
namespace meta_hpp::detail \
{ \
template <> \
struct size_traits<T> { \
std::size_t operator()(const T& v) const { \
using std::size; \
return size(v); \
} \
}; \
}

namespace meta_hpp::detail
{
template < typename T >
Expand Down Expand Up @@ -11323,9 +11392,11 @@ namespace meta_hpp
void (*const move)(uvalue&& self, uvalue& to) noexcept;
void (*const reset)(uvalue& self) noexcept;

uvalue (*const index)(const storage_u& self, std::size_t i);
std::size_t (*const size)(const storage_u& self);

uvalue (*const copy)(const storage_u& self);
uvalue (*const deref)(const storage_u& self);
uvalue (*const index)(const storage_u& self, std::size_t i);
uvalue (*const unmap)(const storage_u& self);

bool (*const less)(const storage_u& l, const storage_u& r);
Expand Down Expand Up @@ -11493,6 +11564,26 @@ namespace meta_hpp
self.storage_.vtag = 0;
}},

.index{[]() {
if constexpr ( detail::has_index_traits<Tp> ) {
return +[](const storage_u& self, std::size_t i) -> uvalue {
return detail::index_traits<Tp>{}(*storage_cast<Tp>(self), i);
};
} else {
return nullptr;
}
}()},

.size{[]() {
if constexpr ( detail::has_size_traits<Tp> ) {
return +[](const storage_u& self) -> std::size_t {
return detail::size_traits<Tp>{}(*storage_cast<Tp>(self));
};
} else {
return nullptr;
}
}()},

.copy{[]() {
if constexpr ( detail::has_copy_traits<Tp> ) {
return +[](const storage_u& self) -> uvalue {
Expand All @@ -11513,16 +11604,6 @@ namespace meta_hpp
}
}()},

.index{[]() {
if constexpr ( detail::has_index_traits<Tp> ) {
return +[](const storage_u& self, std::size_t i) -> uvalue {
return detail::index_traits<Tp>{}(*storage_cast<Tp>(self), i);
};
} else {
return nullptr;
}
}()},

.unmap{[]() {
if constexpr ( detail::has_unmap_traits<Tp> ) {
return +[](const storage_u& self) -> uvalue {
Expand Down Expand Up @@ -11749,6 +11830,21 @@ namespace meta_hpp
return tag != storage_e::nothing && vtable->unmap != nullptr;
}

inline std::size_t uvalue::size() const {
auto&& [tag, vtable] = vtable_t::unpack_vtag(*this);

if ( tag != storage_e::nothing && vtable->size != nullptr ) {
return vtable->size(storage_);
}

throw_exception(error_code::bad_uvalue_operation);
}

inline bool uvalue::has_size_op() const noexcept {
auto&& [tag, vtable] = vtable_t::unpack_vtag(*this);
return tag != storage_e::nothing && vtable->size != nullptr;
}

inline bool uvalue::less(const uvalue& other) const {
if ( this == &other ) {
return false;
Expand Down
33 changes: 33 additions & 0 deletions develop/untests/meta_utilities/value_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ namespace
return {l.x + r.x, l.y + r.y};
}

[[maybe_unused]]
std::size_t size(const ivec2&) {
return 2;
}

[[maybe_unused]]
bool operator==(const ivec2& l, const ivec2& r) noexcept {
return l.x == r.x && l.y == r.y;
Expand Down Expand Up @@ -136,6 +141,7 @@ META_HPP_DECLARE_COPY_TRAITS_FOR(ivec2_big)
META_HPP_DECLARE_DEREF_TRAITS_FOR(deref_custom_class)

META_HPP_DECLARE_INDEX_TRAITS_FOR(ivec2)
META_HPP_DECLARE_SIZE_TRAITS_FOR(ivec2)

META_HPP_DECLARE_EQUALS_TRAITS_FOR(ivec2)

Expand Down Expand Up @@ -911,7 +917,9 @@ TEST_CASE("meta/meta_utilities/value/arrays") {
meta::uvalue v{42};
CHECK(v.get_type() == meta::resolve_type<int>());
CHECK_FALSE(v.has_index_op());
CHECK_FALSE(v.has_size_op());
CHECK_THROWS(std::ignore = v[0]);
CHECK_THROWS(std::ignore = v.size());
}

SUBCASE("void*") {
Expand All @@ -920,7 +928,9 @@ TEST_CASE("meta/meta_utilities/value/arrays") {
meta::uvalue v{p};
CHECK(v.get_type() == meta::resolve_type<void*>());
CHECK_FALSE(v.has_index_op());
CHECK_FALSE(v.has_size_op());
CHECK_THROWS(std::ignore = v[0]);
CHECK_THROWS(std::ignore = v.size());
}

SUBCASE("const void*") {
Expand All @@ -929,7 +939,9 @@ TEST_CASE("meta/meta_utilities/value/arrays") {
meta::uvalue v{p};
CHECK(v.get_type() == meta::resolve_type<const void*>());
CHECK_FALSE(v.has_index_op());
CHECK_FALSE(v.has_size_op());
CHECK_THROWS(std::ignore = v[0]);
CHECK_THROWS(std::ignore = v.size());
}

SUBCASE("int[3]") {
Expand All @@ -938,7 +950,9 @@ TEST_CASE("meta/meta_utilities/value/arrays") {
meta::uvalue v{arr};
CHECK(v.get_type() == meta::resolve_type<int*>());
CHECK(v.has_index_op());
CHECK_FALSE(v.has_size_op());

CHECK_THROWS(std::ignore = v.size());
CHECK(v[0].as<int>() == 1);
CHECK(v[1].as<int>() == 2);
CHECK(v[2].as<int>() == 3);
Expand All @@ -948,6 +962,8 @@ TEST_CASE("meta/meta_utilities/value/arrays") {
meta::uvalue v{arr};
CHECK(v.get_type() == meta::resolve_type<int*>());
CHECK(v.has_index_op());
CHECK_FALSE(v.has_size_op());
CHECK_THROWS(std::ignore = v.size());
CHECK_FALSE(v[0]);
}
}
Expand All @@ -958,7 +974,9 @@ TEST_CASE("meta/meta_utilities/value/arrays") {
meta::uvalue v{arr};
CHECK(v.get_type() == meta::resolve_type<const int*>());
CHECK(v.has_index_op());
CHECK_FALSE(v.has_size_op());

CHECK_THROWS(std::ignore = v.size());
CHECK(v[0].as<int>() == 1);
CHECK(v[1].as<int>() == 2);
CHECK(v[2].as<int>() == 3);
Expand All @@ -968,6 +986,8 @@ TEST_CASE("meta/meta_utilities/value/arrays") {
meta::uvalue v{arr};
CHECK(v.get_type() == meta::resolve_type<const int*>());
CHECK(v.has_index_op());
CHECK_FALSE(v.has_size_op());
CHECK_THROWS(std::ignore = v.size());
CHECK_FALSE(v[0]);
}
}
Expand All @@ -976,7 +996,9 @@ TEST_CASE("meta/meta_utilities/value/arrays") {
meta::uvalue v{std::array{1,2,3}};
CHECK(v.get_type() == meta::resolve_type<std::array<int, 3>>());
CHECK(v.has_index_op());
CHECK(v.has_size_op());

CHECK(v.size() == 3);
CHECK(v[0].as<int>() == 1);
CHECK(v[1].as<int>() == 2);
CHECK(v[2].as<int>() == 3);
Expand All @@ -988,6 +1010,7 @@ TEST_CASE("meta/meta_utilities/value/arrays") {
CHECK(v.get_type() == meta::resolve_type<std::string>());
CHECK(v.has_index_op());

CHECK(v.size() == 3);
CHECK(v[0].as<char>() == 'h');
CHECK(v[1].as<char>() == 'i');
CHECK(v[2].as<char>() == '!');
Expand All @@ -998,7 +1021,9 @@ TEST_CASE("meta/meta_utilities/value/arrays") {
meta::uvalue v{std::string_view{"hi!"}};
CHECK(v.get_type() == meta::resolve_type<std::string_view>());
CHECK(v.has_index_op());
CHECK(v.has_size_op());

CHECK(v.size() == 3);
CHECK(v[0].as<char>() == 'h');
CHECK(v[1].as<char>() == 'i');
CHECK(v[2].as<char>() == '!');
Expand All @@ -1010,7 +1035,9 @@ TEST_CASE("meta/meta_utilities/value/arrays") {
meta::uvalue v{std::span{arr}};
CHECK(v.get_type() == meta::resolve_type<std::span<int>>());
CHECK(v.has_index_op());
CHECK(v.has_size_op());

CHECK(v.size() == 3);
CHECK(v[0].as<int>() == 1);
CHECK(v[1].as<int>() == 2);
CHECK(v[2].as<int>() == 3);
Expand All @@ -1021,7 +1048,9 @@ TEST_CASE("meta/meta_utilities/value/arrays") {
const meta::uvalue v{std::vector{1,2,3}};
CHECK(v.get_type() == meta::resolve_type<std::vector<int>>());
CHECK(v.has_index_op());
CHECK(v.has_size_op());

CHECK(v.size() == 3);
CHECK(v[0].as<int>() == 1);
CHECK(v[1].as<int>() == 2);
CHECK(v[2].as<int>() == 3);
Expand All @@ -1033,14 +1062,18 @@ TEST_CASE("meta/meta_utilities/value/arrays") {
meta::uvalue v{ivec2{1,2}};
CHECK(v.get_type() == meta::resolve_type<ivec2>());
CHECK(v.has_index_op());
CHECK(v.has_size_op());

CHECK(v.size() == 2);
CHECK(v[0].as<int>() == 1);
CHECK(v[1].as<int>() == 2);
}
{
meta::uvalue v{ivec3{1,2,3}};
CHECK(v.get_type() == meta::resolve_type<ivec3>());
CHECK_FALSE(v.has_index_op());
CHECK_FALSE(v.has_size_op());
CHECK_THROWS(std::ignore = v.size());
CHECK_THROWS(std::ignore = v[0]);
}
}
Expand Down
1 change: 1 addition & 0 deletions headers/meta.hpp/meta_base/base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <exception>
#include <functional>
#include <initializer_list>
#include <iterator>
#include <map>
#include <memory>
#include <mutex>
Expand Down
Loading

0 comments on commit 166e6f3

Please sign in to comment.