mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-12 18:56:14 +07:00
new uvalue's size_traits
discussion: https://github.com/BlackMATov/meta.hpp/issues/114
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@@ -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;
|
||||
|
||||
@@ -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 >
|
||||
@@ -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);
|
||||
@@ -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 {
|
||||
@@ -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 {
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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)
|
||||
|
||||
@@ -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*") {
|
||||
@@ -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*") {
|
||||
@@ -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]") {
|
||||
@@ -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);
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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>() == '!');
|
||||
@@ -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>() == '!');
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -1033,7 +1062,9 @@ 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);
|
||||
}
|
||||
@@ -1041,6 +1072,8 @@ TEST_CASE("meta/meta_utilities/value/arrays") {
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
75
headers/meta.hpp/meta_detail/value_traits/size_traits.hpp
Normal file
75
headers/meta.hpp/meta_detail/value_traits/size_traits.hpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/*******************************************************************************
|
||||
* 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-2025, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../meta_base.hpp"
|
||||
#include "../../meta_uvalue.hpp"
|
||||
|
||||
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); \
|
||||
} \
|
||||
}; \
|
||||
}
|
||||
@@ -77,6 +77,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;
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "../meta_detail/value_traits/equals_traits.hpp"
|
||||
#include "../meta_detail/value_traits/index_traits.hpp"
|
||||
#include "../meta_detail/value_traits/less_traits.hpp"
|
||||
#include "../meta_detail/value_traits/size_traits.hpp"
|
||||
#include "../meta_detail/value_traits/unmap_traits.hpp"
|
||||
|
||||
#include "../meta_detail/value_utilities/uarg.hpp"
|
||||
@@ -29,9 +30,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);
|
||||
@@ -199,6 +202,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 {
|
||||
@@ -219,16 +242,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 {
|
||||
@@ -455,6 +468,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;
|
||||
|
||||
@@ -191,6 +191,9 @@ public:
|
||||
uvalue unmap() const;
|
||||
bool has_unmap_op() const noexcept;
|
||||
|
||||
std::size_t size() const;
|
||||
bool has_size_op() const noexcept;
|
||||
|
||||
bool less(const uvalue& other) const;
|
||||
bool has_less_op() const noexcept;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user