mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-14 11:40:35 +07:00
safe deref/index uvalue's operators
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <concepts>
|
||||
#include <deque>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <map>
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace meta_hpp::detail
|
||||
requires std::is_copy_constructible_v<T>
|
||||
struct deref_traits<T*> {
|
||||
uvalue operator()(T* v) const {
|
||||
return uvalue{*v};
|
||||
return v != nullptr ? uvalue{*v} : uvalue{};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace meta_hpp::detail
|
||||
requires std::is_copy_constructible_v<T>
|
||||
struct deref_traits<const T*> {
|
||||
uvalue operator()(const T* v) const {
|
||||
return uvalue{*v};
|
||||
return v != nullptr ? uvalue{*v} : uvalue{};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace meta_hpp::detail
|
||||
requires std::is_copy_constructible_v<T>
|
||||
struct deref_traits<std::shared_ptr<T>> {
|
||||
uvalue operator()(const std::shared_ptr<T>& v) const {
|
||||
return uvalue{*v};
|
||||
return v != nullptr ? uvalue{*v} : uvalue{};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace meta_hpp::detail
|
||||
requires std::is_copy_constructible_v<T>
|
||||
struct deref_traits<std::unique_ptr<T>> {
|
||||
uvalue operator()(const std::unique_ptr<T>& v) const {
|
||||
return uvalue{*v};
|
||||
return v != nullptr ? uvalue{*v} : uvalue{};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace meta_hpp::detail
|
||||
struct index_traits<T*> {
|
||||
uvalue operator()(T* v, std::size_t i) const {
|
||||
// NOLINTNEXTLINE(*-pointer-arithmetic)
|
||||
return uvalue{v[i]};
|
||||
return v != nullptr ? uvalue{v[i]} : uvalue{};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace meta_hpp::detail
|
||||
struct index_traits<const T*> {
|
||||
uvalue operator()(const T* v, std::size_t i) const {
|
||||
// NOLINTNEXTLINE(*-pointer-arithmetic)
|
||||
return uvalue{v[i]};
|
||||
return v != nullptr ? uvalue{v[i]} : uvalue{};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -44,7 +44,15 @@ namespace meta_hpp::detail
|
||||
requires std::is_copy_constructible_v<T>
|
||||
struct index_traits<std::array<T, Size>> {
|
||||
uvalue operator()(const std::array<T, Size>& v, std::size_t i) const {
|
||||
return uvalue{v[i]};
|
||||
return i < v.size() ? uvalue{v[i]} : uvalue{};
|
||||
}
|
||||
};
|
||||
|
||||
template < typename T, typename Allocator >
|
||||
requires std::is_copy_constructible_v<T>
|
||||
struct index_traits<std::deque<T, Allocator>> {
|
||||
uvalue operator()(const std::deque<T, Allocator>& v, std::size_t i) {
|
||||
return i < v.size() ? uvalue{v[i]} : uvalue{};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -52,7 +60,7 @@ namespace meta_hpp::detail
|
||||
requires std::is_copy_constructible_v<T>
|
||||
struct index_traits<std::span<T, Extent>> {
|
||||
uvalue operator()(const std::span<T, Extent>& v, std::size_t i) const {
|
||||
return uvalue{v[i]};
|
||||
return i < v.size() ? uvalue{v[i]} : uvalue{};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -60,7 +68,7 @@ namespace meta_hpp::detail
|
||||
requires std::is_copy_constructible_v<T>
|
||||
struct index_traits<std::basic_string<T, Traits, Allocator>> {
|
||||
uvalue operator()(const std::basic_string<T, Traits, Allocator>& v, std::size_t i) const {
|
||||
return uvalue{v[i]};
|
||||
return i < v.size() ? uvalue{v[i]} : uvalue{};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -68,7 +76,7 @@ namespace meta_hpp::detail
|
||||
requires std::is_copy_constructible_v<T>
|
||||
struct index_traits<std::vector<T, Allocator>> {
|
||||
uvalue operator()(const std::vector<T, Allocator>& v, std::size_t i) {
|
||||
return uvalue{v[i]};
|
||||
return i < v.size() ? uvalue{v[i]} : uvalue{};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -83,7 +83,10 @@ namespace meta_hpp
|
||||
[[nodiscard]] const void* get_cdata() const noexcept;
|
||||
|
||||
[[nodiscard]] uvalue operator*() const;
|
||||
[[nodiscard]] bool has_deref_op() const noexcept;
|
||||
|
||||
[[nodiscard]] uvalue operator[](std::size_t index) const;
|
||||
[[nodiscard]] bool has_index_op() const noexcept;
|
||||
|
||||
template < typename T >
|
||||
[[nodiscard]] T get_as() &&;
|
||||
|
||||
@@ -180,21 +180,26 @@ namespace meta_hpp
|
||||
self.vtable_ = nullptr;
|
||||
},
|
||||
|
||||
.deref = +[]([[maybe_unused]] const storage_u& from) -> uvalue {
|
||||
if constexpr ( detail::has_deref_traits<Tp> ) {
|
||||
return detail::deref_traits<Tp>{}(*storage_cast<Tp>(from));
|
||||
} else {
|
||||
META_HPP_THROW_AS(exception, "value type doesn't have value deref traits");
|
||||
}
|
||||
},
|
||||
|
||||
.index = +[]([[maybe_unused]] const storage_u& from, [[maybe_unused]] std::size_t i) -> uvalue {
|
||||
if constexpr ( detail::has_index_traits<Tp> ) {
|
||||
return detail::index_traits<Tp>{}(*storage_cast<Tp>(from), i);
|
||||
.deref = [](){
|
||||
if constexpr ( detail::has_deref_traits<Tp> ) {
|
||||
return +[](const storage_u& from) -> uvalue {
|
||||
return detail::deref_traits<Tp>{}(*storage_cast<Tp>(from));
|
||||
};
|
||||
} else {
|
||||
META_HPP_THROW_AS(exception, "value type doesn't have value index traits");
|
||||
return nullptr;
|
||||
}
|
||||
},
|
||||
}(),
|
||||
|
||||
.index = [](){
|
||||
if constexpr ( detail::has_index_traits<Tp> ) {
|
||||
return +[](const storage_u& from, std::size_t i) -> uvalue {
|
||||
return detail::index_traits<Tp>{}(*storage_cast<Tp>(from), i);
|
||||
};
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}(),
|
||||
};
|
||||
|
||||
return &table;
|
||||
@@ -318,11 +323,19 @@ namespace meta_hpp
|
||||
}
|
||||
|
||||
inline uvalue uvalue::operator*() const {
|
||||
return vtable_ != nullptr ? vtable_->deref(storage_) : uvalue{};
|
||||
return has_deref_op() ? vtable_->deref(storage_) : uvalue{};
|
||||
}
|
||||
|
||||
inline bool uvalue::has_deref_op() const noexcept {
|
||||
return vtable_ != nullptr && vtable_->deref != nullptr;
|
||||
}
|
||||
|
||||
inline uvalue uvalue::operator[](std::size_t index) const {
|
||||
return vtable_ != nullptr ? vtable_->index(storage_, index) : uvalue{};
|
||||
return has_index_op() ? vtable_->index(storage_, index) : uvalue{};
|
||||
}
|
||||
|
||||
inline bool uvalue::has_index_op() const noexcept {
|
||||
return vtable_ != nullptr && vtable_->index != nullptr;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
|
||||
Reference in New Issue
Block a user