mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-14 11:40:35 +07:00
uvalue simplifying and usage example
This commit is contained in:
@@ -61,40 +61,15 @@ namespace meta_hpp
|
|||||||
[[nodiscard]] uvalue operator[](std::size_t index) const;
|
[[nodiscard]] uvalue operator[](std::size_t index) const;
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
[[nodiscard]] T get_as() &;
|
[[nodiscard]] auto get_as()
|
||||||
template < typename T >
|
-> std::conditional_t<detail::pointer_kind<T>, T, T&>;
|
||||||
[[nodiscard]] T get_as() &&;
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] T get_as() const &;
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] T get_as() const &&;
|
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
[[nodiscard]] T& get_as_ref() &;
|
[[nodiscard]] auto get_as() const
|
||||||
template < typename T >
|
-> std::conditional_t<detail::pointer_kind<T>, T, const T&>;
|
||||||
[[nodiscard]] T&& get_as_ref() &&;
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] const T& get_as_ref() const &;
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] const T&& get_as_ref() const &&;
|
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
[[nodiscard]] bool can_get_as() &;
|
[[nodiscard]] bool can_get_as() const noexcept;
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] bool can_get_as() &&;
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] bool can_get_as() const &;
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] bool can_get_as() const &&;
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] bool can_get_as_ref() &;
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] bool can_get_as_ref() &&;
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] bool can_get_as_ref() const &;
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] bool can_get_as_ref() const &&;
|
|
||||||
|
|
||||||
friend bool operator<(const uvalue& l, const uvalue& r);
|
friend bool operator<(const uvalue& l, const uvalue& r);
|
||||||
friend bool operator==(const uvalue& l, const uvalue& r);
|
friend bool operator==(const uvalue& l, const uvalue& r);
|
||||||
@@ -116,18 +91,3 @@ namespace meta_hpp
|
|||||||
l.swap(r);
|
l.swap(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace meta_hpp
|
|
||||||
{
|
|
||||||
template < typename T, detail::decay_value_kind V >
|
|
||||||
[[nodiscard]] auto get_as(V&& value) -> T;
|
|
||||||
|
|
||||||
template < typename T, detail::decay_value_kind V >
|
|
||||||
[[nodiscard]] auto get_as_ref(V&& value) -> detail::add_cvref_t<V&&, T>;
|
|
||||||
|
|
||||||
template < typename T, detail::decay_value_kind V >
|
|
||||||
[[nodiscard]] bool can_get_as(V&& value) noexcept;
|
|
||||||
|
|
||||||
template < typename T, detail::decay_value_kind V >
|
|
||||||
[[nodiscard]] bool can_get_as_ref(V&& value) noexcept;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ namespace meta_hpp
|
|||||||
|
|
||||||
.deref = +[]([[maybe_unused]] const uvalue& v) -> uvalue {
|
.deref = +[]([[maybe_unused]] const uvalue& v) -> uvalue {
|
||||||
if constexpr ( detail::has_deref_traits<Tp> ) {
|
if constexpr ( detail::has_deref_traits<Tp> ) {
|
||||||
return detail::deref_traits<Tp>{}(v.get_as_ref<Tp>());
|
return detail::deref_traits<Tp>{}(v.get_as<Tp>());
|
||||||
} else {
|
} else {
|
||||||
detail::throw_exception_with("value type doesn't have value deref traits");
|
detail::throw_exception_with("value type doesn't have value deref traits");
|
||||||
}
|
}
|
||||||
@@ -194,7 +194,7 @@ namespace meta_hpp
|
|||||||
|
|
||||||
.index = +[]([[maybe_unused]] const uvalue& v, [[maybe_unused]] std::size_t i) -> uvalue {
|
.index = +[]([[maybe_unused]] const uvalue& v, [[maybe_unused]] std::size_t i) -> uvalue {
|
||||||
if constexpr ( detail::has_index_traits<Tp> ) {
|
if constexpr ( detail::has_index_traits<Tp> ) {
|
||||||
return detail::index_traits<Tp>{}(v.get_as_ref<Tp>(), i);
|
return detail::index_traits<Tp>{}(v.get_as<Tp>(), i);
|
||||||
} else {
|
} else {
|
||||||
detail::throw_exception_with("value type doesn't have value index traits");
|
detail::throw_exception_with("value type doesn't have value index traits");
|
||||||
}
|
}
|
||||||
@@ -202,7 +202,7 @@ namespace meta_hpp
|
|||||||
|
|
||||||
.less = +[]([[maybe_unused]] const uvalue& l, [[maybe_unused]] const uvalue& r) -> bool {
|
.less = +[]([[maybe_unused]] const uvalue& l, [[maybe_unused]] const uvalue& r) -> bool {
|
||||||
if constexpr ( detail::has_less_traits<Tp> ) {
|
if constexpr ( detail::has_less_traits<Tp> ) {
|
||||||
return detail::less_traits<Tp>{}(l.get_as_ref<Tp>(), r.get_as_ref<Tp>());
|
return detail::less_traits<Tp>{}(l.get_as<Tp>(), r.get_as<Tp>());
|
||||||
} else {
|
} else {
|
||||||
detail::throw_exception_with("value type doesn't have value less traits");
|
detail::throw_exception_with("value type doesn't have value less traits");
|
||||||
}
|
}
|
||||||
@@ -210,23 +210,23 @@ namespace meta_hpp
|
|||||||
|
|
||||||
.equals = +[]([[maybe_unused]] const uvalue& l, [[maybe_unused]] const uvalue& r) -> bool {
|
.equals = +[]([[maybe_unused]] const uvalue& l, [[maybe_unused]] const uvalue& r) -> bool {
|
||||||
if constexpr ( detail::has_equals_traits<Tp> ) {
|
if constexpr ( detail::has_equals_traits<Tp> ) {
|
||||||
return detail::equals_traits<Tp>{}(l.get_as_ref<Tp>(), r.get_as_ref<Tp>());
|
return detail::equals_traits<Tp>{}(l.get_as<Tp>(), r.get_as<Tp>());
|
||||||
} else {
|
} else {
|
||||||
detail::throw_exception_with("value type doesn't have value equals traits");
|
detail::throw_exception_with("value type doesn't have value equals traits");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
.istream = +[]([[maybe_unused]] std::istream& is, [[maybe_unused]] uvalue& v) -> std::istream& {
|
.istream = +[]([[maybe_unused]] std::istream& is, [[maybe_unused]] uvalue& v) -> std::istream& {
|
||||||
if constexpr ( detail::has_istream_traits<Tp> ) {
|
if constexpr ( detail::has_istream_traits<Tp> && !detail::pointer_kind<Tp> ) {
|
||||||
return detail::istream_traits<Tp>{}(is, v.get_as_ref<Tp>());
|
return detail::istream_traits<Tp>{}(is, v.get_as<Tp>());
|
||||||
} else {
|
} else {
|
||||||
detail::throw_exception_with("value type doesn't have value istream traits");
|
detail::throw_exception_with("value type doesn't have value istream traits");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
.ostream = +[]([[maybe_unused]] std::ostream& os, [[maybe_unused]] const uvalue& v) -> std::ostream& {
|
.ostream = +[]([[maybe_unused]] std::ostream& os, [[maybe_unused]] const uvalue& v) -> std::ostream& {
|
||||||
if constexpr ( detail::has_ostream_traits<Tp> ) {
|
if constexpr ( detail::has_ostream_traits<Tp> && !detail::pointer_kind<Tp> ) {
|
||||||
return detail::ostream_traits<Tp>{}(os, v.get_as_ref<Tp>());
|
return detail::ostream_traits<Tp>{}(os, v.get_as<Tp>());
|
||||||
} else {
|
} else {
|
||||||
detail::throw_exception_with("value type doesn't have value ostream traits");
|
detail::throw_exception_with("value type doesn't have value ostream traits");
|
||||||
}
|
}
|
||||||
@@ -327,106 +327,15 @@ namespace meta_hpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
T uvalue::get_as() & {
|
auto uvalue::get_as() -> std::conditional_t<detail::pointer_kind<T>, T, T&> {
|
||||||
return meta_hpp::get_as<T>(*this);
|
static_assert(std::is_same_v<T, std::decay_t<T>>);
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
const any_type& from_type = get_type();
|
||||||
T uvalue::get_as() && {
|
const any_type& to_type = resolve_type<T>();
|
||||||
return meta_hpp::get_as<T>(std::move(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
T uvalue::get_as() const & {
|
|
||||||
return meta_hpp::get_as<T>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
T uvalue::get_as() const && {
|
|
||||||
// NOLINTNEXTLINE(*-move-const-arg)
|
|
||||||
return meta_hpp::get_as<T>(std::move(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
T& uvalue::get_as_ref() & {
|
|
||||||
return meta_hpp::get_as_ref<T>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
T&& uvalue::get_as_ref() && {
|
|
||||||
return meta_hpp::get_as_ref<T>(std::move(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
const T& uvalue::get_as_ref() const & {
|
|
||||||
return meta_hpp::get_as_ref<T>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
const T&& uvalue::get_as_ref() const && {
|
|
||||||
// NOLINTNEXTLINE(*-move-const-arg)
|
|
||||||
return meta_hpp::get_as_ref<T>(std::move(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
bool uvalue::can_get_as() & {
|
|
||||||
return meta_hpp::can_get_as<T>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
bool uvalue::can_get_as() && {
|
|
||||||
return meta_hpp::can_get_as<T>(std::move(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
bool uvalue::can_get_as() const & {
|
|
||||||
return meta_hpp::can_get_as<T>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
bool uvalue::can_get_as() const && {
|
|
||||||
// NOLINTNEXTLINE(*-move-const-arg)
|
|
||||||
return meta_hpp::can_get_as<T>(std::move(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
bool uvalue::can_get_as_ref() & {
|
|
||||||
return meta_hpp::can_get_as_ref<T>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
bool uvalue::can_get_as_ref() && {
|
|
||||||
return meta_hpp::can_get_as_ref<T>(std::move(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
bool uvalue::can_get_as_ref() const & {
|
|
||||||
return meta_hpp::can_get_as_ref<T>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
bool uvalue::can_get_as_ref() const && {
|
|
||||||
// NOLINTNEXTLINE(*-move-const-arg)
|
|
||||||
return meta_hpp::can_get_as_ref<T>(std::move(*this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace meta_hpp
|
|
||||||
{
|
|
||||||
template < typename T, detail::decay_value_kind V >
|
|
||||||
[[nodiscard]] auto get_as(V&& value) -> T {
|
|
||||||
using Tp = std::decay_t<T>;
|
|
||||||
static_assert(std::is_constructible_v<T, detail::add_cvref_t<V&&, Tp>>);
|
|
||||||
|
|
||||||
const any_type& from_type = value.get_type();
|
|
||||||
const any_type& to_type = resolve_type<Tp>();
|
|
||||||
|
|
||||||
if ( from_type == to_type ) {
|
if ( from_type == to_type ) {
|
||||||
using to_ptr_t = detail::add_cv_t<V, Tp>*;
|
T* to_ptr = static_cast<T*>(data());
|
||||||
auto to_ptr = static_cast<to_ptr_t>(value.data());
|
return *to_ptr;
|
||||||
return static_cast<T>(*to_ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto is_a = [](const any_type& base, const any_type& derived){
|
const auto is_a = [](const any_type& base, const any_type& derived){
|
||||||
@@ -438,12 +347,11 @@ namespace meta_hpp
|
|||||||
const class_type& to_class = to_type.as_class();
|
const class_type& to_class = to_type.as_class();
|
||||||
const class_type& from_class = from_type.as_class();
|
const class_type& from_class = from_type.as_class();
|
||||||
|
|
||||||
using to_ptr_t = detail::add_cv_t<V, Tp>*;
|
T* to_ptr = static_cast<T*>(detail::pointer_upcast(data(), from_class, to_class));
|
||||||
auto to_ptr = static_cast<to_ptr_t>(detail::pointer_upcast(value.data(), from_class, to_class));
|
return *to_ptr;
|
||||||
return static_cast<T>(*to_ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr ( std::is_pointer_v<T> ) {
|
if constexpr ( detail::pointer_kind<T> ) {
|
||||||
if ( to_type.is_pointer() && from_type.is_nullptr() ) {
|
if ( to_type.is_pointer() && from_type.is_nullptr() ) {
|
||||||
return static_cast<T>(nullptr);
|
return static_cast<T>(nullptr);
|
||||||
}
|
}
|
||||||
@@ -459,11 +367,11 @@ namespace meta_hpp
|
|||||||
const any_type& from_data_type = from_type_ptr.get_data_type();
|
const any_type& from_data_type = from_type_ptr.get_data_type();
|
||||||
|
|
||||||
if ( to_type_ptr_readonly >= from_type_ptr_readonly ) {
|
if ( to_type_ptr_readonly >= from_type_ptr_readonly ) {
|
||||||
using from_data_ptr_t = detail::add_cv_t<V, void*>*;
|
void** from_data_ptr = static_cast<void**>(data());
|
||||||
auto from_data_ptr = static_cast<from_data_ptr_t>(value.data());
|
|
||||||
|
|
||||||
if ( to_data_type.is_void() || to_data_type == from_data_type ) {
|
if ( to_data_type.is_void() || to_data_type == from_data_type ) {
|
||||||
return static_cast<T>(*from_data_ptr);
|
void* to_ptr = *from_data_ptr;
|
||||||
|
return static_cast<T>(to_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( is_a(to_data_type, from_data_type) ) {
|
if ( is_a(to_data_type, from_data_type) ) {
|
||||||
@@ -480,19 +388,74 @@ namespace meta_hpp
|
|||||||
detail::throw_exception_with("bad value cast");
|
detail::throw_exception_with("bad value cast");
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T, detail::decay_value_kind V >
|
template < typename T >
|
||||||
[[nodiscard]] auto get_as_ref(V&& value) -> detail::add_cvref_t<V&&, T> {
|
auto uvalue::get_as() const -> std::conditional_t<detail::pointer_kind<T>, T, const T&> {
|
||||||
static_assert(!std::is_reference_v<T>);
|
static_assert(std::is_same_v<T, std::decay_t<T>>);
|
||||||
return get_as<detail::add_cvref_t<V&&, T>>(std::forward<V>(value));
|
|
||||||
|
const any_type& from_type = get_type();
|
||||||
|
const any_type& to_type = resolve_type<T>();
|
||||||
|
|
||||||
|
if ( from_type == to_type ) {
|
||||||
|
const T* to_ptr = static_cast<const T*>(data());
|
||||||
|
return *to_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto is_a = [](const any_type& base, const any_type& derived){
|
||||||
|
return (base == derived)
|
||||||
|
|| (base.is_class() && derived.is_class() && base.as_class().is_base_of(derived.as_class()));
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( is_a(to_type, from_type) ) {
|
||||||
|
const class_type& to_class = to_type.as_class();
|
||||||
|
const class_type& from_class = from_type.as_class();
|
||||||
|
|
||||||
|
const T* to_ptr = static_cast<const T*>(detail::pointer_upcast(data(), from_class, to_class));
|
||||||
|
return *to_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr ( detail::pointer_kind<T> ) {
|
||||||
|
if ( to_type.is_pointer() && from_type.is_nullptr() ) {
|
||||||
|
return static_cast<T>(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( to_type.is_pointer() && from_type.is_pointer() ) {
|
||||||
|
const pointer_type& to_type_ptr = to_type.as_pointer();
|
||||||
|
const bool to_type_ptr_readonly = to_type_ptr.get_flags().has(pointer_flags::is_readonly);
|
||||||
|
|
||||||
|
const pointer_type& from_type_ptr = from_type.as_pointer();
|
||||||
|
const bool from_type_ptr_readonly = from_type_ptr.get_flags().has(pointer_flags::is_readonly);
|
||||||
|
|
||||||
|
const any_type& to_data_type = to_type_ptr.get_data_type();
|
||||||
|
const any_type& from_data_type = from_type_ptr.get_data_type();
|
||||||
|
|
||||||
|
if ( to_type_ptr_readonly >= from_type_ptr_readonly ) {
|
||||||
|
void* const* from_data_ptr = static_cast<void* const*>(data());
|
||||||
|
|
||||||
|
if ( to_data_type.is_void() || to_data_type == from_data_type ) {
|
||||||
|
void* to_ptr = *from_data_ptr;
|
||||||
|
return static_cast<T>(to_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( is_a(to_data_type, from_data_type) ) {
|
||||||
|
const class_type& to_data_class = to_data_type.as_class();
|
||||||
|
const class_type& from_data_class = from_data_type.as_class();
|
||||||
|
|
||||||
|
void* to_ptr = detail::pointer_upcast(*from_data_ptr, from_data_class, to_data_class);
|
||||||
|
return static_cast<T>(to_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
detail::throw_exception_with("bad value cast");
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T, detail::decay_value_kind V >
|
template < typename T >
|
||||||
[[nodiscard]] bool can_get_as(V&& value) noexcept {
|
bool uvalue::can_get_as() const noexcept {
|
||||||
using Tp = std::decay_t<T>;
|
static_assert(std::is_same_v<T, std::decay_t<T>>);
|
||||||
static_assert(std::is_constructible_v<T, detail::add_cvref_t<V&&, Tp>>);
|
|
||||||
|
|
||||||
const any_type& from_type = value.get_type();
|
const any_type& from_type = get_type();
|
||||||
const any_type& to_type = resolve_type<Tp>();
|
const any_type& to_type = resolve_type<T>();
|
||||||
|
|
||||||
if ( from_type == to_type ) {
|
if ( from_type == to_type ) {
|
||||||
return true;
|
return true;
|
||||||
@@ -507,7 +470,7 @@ namespace meta_hpp
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr ( std::is_pointer_v<T> ) {
|
if constexpr ( detail::pointer_kind<T> ) {
|
||||||
if ( to_type.is_pointer() && from_type.is_nullptr() ) {
|
if ( to_type.is_pointer() && from_type.is_nullptr() ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -532,12 +495,6 @@ namespace meta_hpp
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T, detail::decay_value_kind V >
|
|
||||||
[[nodiscard]] bool can_get_as_ref(V&& value) noexcept {
|
|
||||||
static_assert(!std::is_reference_v<T>);
|
|
||||||
return can_get_as<detail::add_cvref_t<V&&, T>>(std::forward<V>(value));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace meta_hpp
|
namespace meta_hpp
|
||||||
@@ -551,7 +508,7 @@ namespace meta_hpp
|
|||||||
const any_type& l_type = l.get_type();
|
const any_type& l_type = l.get_type();
|
||||||
const any_type& r_type = resolve_type<T>();
|
const any_type& r_type = resolve_type<T>();
|
||||||
|
|
||||||
return (l_type < r_type) || (l_type == r_type && l.get_as_ref<T>() < r);
|
return (l_type < r_type) || (l_type == r_type && l.get_as<T>() < r);
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
@@ -563,7 +520,7 @@ namespace meta_hpp
|
|||||||
const any_type& l_type = resolve_type<T>();
|
const any_type& l_type = resolve_type<T>();
|
||||||
const any_type& r_type = r.get_type();
|
const any_type& r_type = r.get_type();
|
||||||
|
|
||||||
return (l_type < r_type) || (l_type == r_type && l < r.get_as_ref<T>());
|
return (l_type < r_type) || (l_type == r_type && l < r.get_as<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline bool operator<(const uvalue& l, const uvalue& r) {
|
[[nodiscard]] inline bool operator<(const uvalue& l, const uvalue& r) {
|
||||||
@@ -593,7 +550,7 @@ namespace meta_hpp
|
|||||||
const any_type& l_type = l.get_type();
|
const any_type& l_type = l.get_type();
|
||||||
const any_type& r_type = resolve_type<T>();
|
const any_type& r_type = resolve_type<T>();
|
||||||
|
|
||||||
return l_type == r_type && l.get_as_ref<T>() == r;
|
return l_type == r_type && l.get_as<T>() == r;
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
@@ -605,7 +562,7 @@ namespace meta_hpp
|
|||||||
const any_type& l_type = resolve_type<T>();
|
const any_type& l_type = resolve_type<T>();
|
||||||
const any_type& r_type = r.get_type();
|
const any_type& r_type = r.get_type();
|
||||||
|
|
||||||
return l_type == r_type && l == r.get_as_ref<T>();
|
return l_type == r_type && l == r.get_as<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline bool operator==(const uvalue& l, const uvalue& r) {
|
[[nodiscard]] inline bool operator==(const uvalue& l, const uvalue& r) {
|
||||||
|
|||||||
83
manuals/meta_examples/uvalue_example.cpp
Normal file
83
manuals/meta_examples/uvalue_example.cpp
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* 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-2022, by Matvey Cherevko (blackmatov@gmail.com)
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "../meta_manuals.hpp"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class shape {
|
||||||
|
public:
|
||||||
|
shape() = default;
|
||||||
|
shape(const shape&) = default;
|
||||||
|
virtual ~shape() = default;
|
||||||
|
|
||||||
|
virtual int get_area() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class rectangle : public shape {
|
||||||
|
public:
|
||||||
|
explicit rectangle(int width, int height)
|
||||||
|
: width_{width}
|
||||||
|
, height_{height} {}
|
||||||
|
|
||||||
|
int get_width() const {
|
||||||
|
return width_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_height() const {
|
||||||
|
return height_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_area() const override {
|
||||||
|
return width_ * height_;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
int width_{};
|
||||||
|
int height_{};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("meta/meta_examples/uvalue") {
|
||||||
|
namespace meta = meta_hpp;
|
||||||
|
|
||||||
|
// 'shape' class type registration
|
||||||
|
meta::class_<shape>()
|
||||||
|
.method_("get_area", &shape::get_area);
|
||||||
|
|
||||||
|
// 'rectangle' class type registration
|
||||||
|
meta::class_<rectangle>()
|
||||||
|
.base_<shape>()
|
||||||
|
.constructor_<int, int>()
|
||||||
|
.method_("get_width", &rectangle::get_width)
|
||||||
|
.method_("get_height", &rectangle::get_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("meta/meta_examples/uvalue/usage") {
|
||||||
|
namespace meta = meta_hpp;
|
||||||
|
|
||||||
|
// the 'uvalue' class allows to store any copyable value inside
|
||||||
|
// it's widely used as return value types and as containers for storing metadata
|
||||||
|
|
||||||
|
meta::uvalue val{42};
|
||||||
|
CHECK(val.get_type() == meta::resolve_type<int>());
|
||||||
|
|
||||||
|
// we can get a reference to the stored data and even change it
|
||||||
|
val.get_as<int>() = 21;
|
||||||
|
CHECK(val.get_as<int>() == 21);
|
||||||
|
|
||||||
|
// uvalue can be copied, assigned, and moved
|
||||||
|
val = rectangle{10, 20};
|
||||||
|
CHECK(val.get_type() == meta::resolve_type<rectangle>());
|
||||||
|
|
||||||
|
// also, it supports upcasting for registered types
|
||||||
|
CHECK(val.get_as<shape>().get_area() == 200);
|
||||||
|
|
||||||
|
// upcasting is supported for pointers too
|
||||||
|
rectangle rect{3, 5};
|
||||||
|
val = ▭
|
||||||
|
CHECK(val.get_as<shape*>()->get_area() == 15);
|
||||||
|
CHECK(val.get_type() == meta::resolve_type<rectangle*>());
|
||||||
|
}
|
||||||
@@ -2263,40 +2263,15 @@ namespace meta_hpp
|
|||||||
[[nodiscard]] uvalue operator[](std::size_t index) const;
|
[[nodiscard]] uvalue operator[](std::size_t index) const;
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
[[nodiscard]] T get_as() &;
|
[[nodiscard]] auto get_as()
|
||||||
template < typename T >
|
-> std::conditional_t<detail::pointer_kind<T>, T, T&>;
|
||||||
[[nodiscard]] T get_as() &&;
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] T get_as() const &;
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] T get_as() const &&;
|
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
[[nodiscard]] T& get_as_ref() &;
|
[[nodiscard]] auto get_as() const
|
||||||
template < typename T >
|
-> std::conditional_t<detail::pointer_kind<T>, T, const T&>;
|
||||||
[[nodiscard]] T&& get_as_ref() &&;
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] const T& get_as_ref() const &;
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] const T&& get_as_ref() const &&;
|
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
[[nodiscard]] bool can_get_as() &;
|
[[nodiscard]] bool can_get_as() const noexcept;
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] bool can_get_as() &&;
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] bool can_get_as() const &;
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] bool can_get_as() const &&;
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] bool can_get_as_ref() &;
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] bool can_get_as_ref() &&;
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] bool can_get_as_ref() const &;
|
|
||||||
template < typename T >
|
|
||||||
[[nodiscard]] bool can_get_as_ref() const &&;
|
|
||||||
|
|
||||||
friend bool operator<(const uvalue& l, const uvalue& r);
|
friend bool operator<(const uvalue& l, const uvalue& r);
|
||||||
friend bool operator==(const uvalue& l, const uvalue& r);
|
friend bool operator==(const uvalue& l, const uvalue& r);
|
||||||
@@ -2319,21 +2294,6 @@ namespace meta_hpp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace meta_hpp
|
|
||||||
{
|
|
||||||
template < typename T, detail::decay_value_kind V >
|
|
||||||
[[nodiscard]] auto get_as(V&& value) -> T;
|
|
||||||
|
|
||||||
template < typename T, detail::decay_value_kind V >
|
|
||||||
[[nodiscard]] auto get_as_ref(V&& value) -> detail::add_cvref_t<V&&, T>;
|
|
||||||
|
|
||||||
template < typename T, detail::decay_value_kind V >
|
|
||||||
[[nodiscard]] bool can_get_as(V&& value) noexcept;
|
|
||||||
|
|
||||||
template < typename T, detail::decay_value_kind V >
|
|
||||||
[[nodiscard]] bool can_get_as_ref(V&& value) noexcept;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace meta_hpp::detail
|
namespace meta_hpp::detail
|
||||||
{
|
{
|
||||||
template < typename T >
|
template < typename T >
|
||||||
@@ -8204,7 +8164,7 @@ namespace meta_hpp
|
|||||||
|
|
||||||
.deref = +[]([[maybe_unused]] const uvalue& v) -> uvalue {
|
.deref = +[]([[maybe_unused]] const uvalue& v) -> uvalue {
|
||||||
if constexpr ( detail::has_deref_traits<Tp> ) {
|
if constexpr ( detail::has_deref_traits<Tp> ) {
|
||||||
return detail::deref_traits<Tp>{}(v.get_as_ref<Tp>());
|
return detail::deref_traits<Tp>{}(v.get_as<Tp>());
|
||||||
} else {
|
} else {
|
||||||
detail::throw_exception_with("value type doesn't have value deref traits");
|
detail::throw_exception_with("value type doesn't have value deref traits");
|
||||||
}
|
}
|
||||||
@@ -8212,7 +8172,7 @@ namespace meta_hpp
|
|||||||
|
|
||||||
.index = +[]([[maybe_unused]] const uvalue& v, [[maybe_unused]] std::size_t i) -> uvalue {
|
.index = +[]([[maybe_unused]] const uvalue& v, [[maybe_unused]] std::size_t i) -> uvalue {
|
||||||
if constexpr ( detail::has_index_traits<Tp> ) {
|
if constexpr ( detail::has_index_traits<Tp> ) {
|
||||||
return detail::index_traits<Tp>{}(v.get_as_ref<Tp>(), i);
|
return detail::index_traits<Tp>{}(v.get_as<Tp>(), i);
|
||||||
} else {
|
} else {
|
||||||
detail::throw_exception_with("value type doesn't have value index traits");
|
detail::throw_exception_with("value type doesn't have value index traits");
|
||||||
}
|
}
|
||||||
@@ -8220,7 +8180,7 @@ namespace meta_hpp
|
|||||||
|
|
||||||
.less = +[]([[maybe_unused]] const uvalue& l, [[maybe_unused]] const uvalue& r) -> bool {
|
.less = +[]([[maybe_unused]] const uvalue& l, [[maybe_unused]] const uvalue& r) -> bool {
|
||||||
if constexpr ( detail::has_less_traits<Tp> ) {
|
if constexpr ( detail::has_less_traits<Tp> ) {
|
||||||
return detail::less_traits<Tp>{}(l.get_as_ref<Tp>(), r.get_as_ref<Tp>());
|
return detail::less_traits<Tp>{}(l.get_as<Tp>(), r.get_as<Tp>());
|
||||||
} else {
|
} else {
|
||||||
detail::throw_exception_with("value type doesn't have value less traits");
|
detail::throw_exception_with("value type doesn't have value less traits");
|
||||||
}
|
}
|
||||||
@@ -8228,23 +8188,23 @@ namespace meta_hpp
|
|||||||
|
|
||||||
.equals = +[]([[maybe_unused]] const uvalue& l, [[maybe_unused]] const uvalue& r) -> bool {
|
.equals = +[]([[maybe_unused]] const uvalue& l, [[maybe_unused]] const uvalue& r) -> bool {
|
||||||
if constexpr ( detail::has_equals_traits<Tp> ) {
|
if constexpr ( detail::has_equals_traits<Tp> ) {
|
||||||
return detail::equals_traits<Tp>{}(l.get_as_ref<Tp>(), r.get_as_ref<Tp>());
|
return detail::equals_traits<Tp>{}(l.get_as<Tp>(), r.get_as<Tp>());
|
||||||
} else {
|
} else {
|
||||||
detail::throw_exception_with("value type doesn't have value equals traits");
|
detail::throw_exception_with("value type doesn't have value equals traits");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
.istream = +[]([[maybe_unused]] std::istream& is, [[maybe_unused]] uvalue& v) -> std::istream& {
|
.istream = +[]([[maybe_unused]] std::istream& is, [[maybe_unused]] uvalue& v) -> std::istream& {
|
||||||
if constexpr ( detail::has_istream_traits<Tp> ) {
|
if constexpr ( detail::has_istream_traits<Tp> && !detail::pointer_kind<Tp> ) {
|
||||||
return detail::istream_traits<Tp>{}(is, v.get_as_ref<Tp>());
|
return detail::istream_traits<Tp>{}(is, v.get_as<Tp>());
|
||||||
} else {
|
} else {
|
||||||
detail::throw_exception_with("value type doesn't have value istream traits");
|
detail::throw_exception_with("value type doesn't have value istream traits");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
.ostream = +[]([[maybe_unused]] std::ostream& os, [[maybe_unused]] const uvalue& v) -> std::ostream& {
|
.ostream = +[]([[maybe_unused]] std::ostream& os, [[maybe_unused]] const uvalue& v) -> std::ostream& {
|
||||||
if constexpr ( detail::has_ostream_traits<Tp> ) {
|
if constexpr ( detail::has_ostream_traits<Tp> && !detail::pointer_kind<Tp> ) {
|
||||||
return detail::ostream_traits<Tp>{}(os, v.get_as_ref<Tp>());
|
return detail::ostream_traits<Tp>{}(os, v.get_as<Tp>());
|
||||||
} else {
|
} else {
|
||||||
detail::throw_exception_with("value type doesn't have value ostream traits");
|
detail::throw_exception_with("value type doesn't have value ostream traits");
|
||||||
}
|
}
|
||||||
@@ -8345,106 +8305,15 @@ namespace meta_hpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
T uvalue::get_as() & {
|
auto uvalue::get_as() -> std::conditional_t<detail::pointer_kind<T>, T, T&> {
|
||||||
return meta_hpp::get_as<T>(*this);
|
static_assert(std::is_same_v<T, std::decay_t<T>>);
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
const any_type& from_type = get_type();
|
||||||
T uvalue::get_as() && {
|
const any_type& to_type = resolve_type<T>();
|
||||||
return meta_hpp::get_as<T>(std::move(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
T uvalue::get_as() const & {
|
|
||||||
return meta_hpp::get_as<T>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
T uvalue::get_as() const && {
|
|
||||||
// NOLINTNEXTLINE(*-move-const-arg)
|
|
||||||
return meta_hpp::get_as<T>(std::move(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
T& uvalue::get_as_ref() & {
|
|
||||||
return meta_hpp::get_as_ref<T>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
T&& uvalue::get_as_ref() && {
|
|
||||||
return meta_hpp::get_as_ref<T>(std::move(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
const T& uvalue::get_as_ref() const & {
|
|
||||||
return meta_hpp::get_as_ref<T>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
const T&& uvalue::get_as_ref() const && {
|
|
||||||
// NOLINTNEXTLINE(*-move-const-arg)
|
|
||||||
return meta_hpp::get_as_ref<T>(std::move(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
bool uvalue::can_get_as() & {
|
|
||||||
return meta_hpp::can_get_as<T>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
bool uvalue::can_get_as() && {
|
|
||||||
return meta_hpp::can_get_as<T>(std::move(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
bool uvalue::can_get_as() const & {
|
|
||||||
return meta_hpp::can_get_as<T>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
bool uvalue::can_get_as() const && {
|
|
||||||
// NOLINTNEXTLINE(*-move-const-arg)
|
|
||||||
return meta_hpp::can_get_as<T>(std::move(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
bool uvalue::can_get_as_ref() & {
|
|
||||||
return meta_hpp::can_get_as_ref<T>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
bool uvalue::can_get_as_ref() && {
|
|
||||||
return meta_hpp::can_get_as_ref<T>(std::move(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
bool uvalue::can_get_as_ref() const & {
|
|
||||||
return meta_hpp::can_get_as_ref<T>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
bool uvalue::can_get_as_ref() const && {
|
|
||||||
// NOLINTNEXTLINE(*-move-const-arg)
|
|
||||||
return meta_hpp::can_get_as_ref<T>(std::move(*this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace meta_hpp
|
|
||||||
{
|
|
||||||
template < typename T, detail::decay_value_kind V >
|
|
||||||
[[nodiscard]] auto get_as(V&& value) -> T {
|
|
||||||
using Tp = std::decay_t<T>;
|
|
||||||
static_assert(std::is_constructible_v<T, detail::add_cvref_t<V&&, Tp>>);
|
|
||||||
|
|
||||||
const any_type& from_type = value.get_type();
|
|
||||||
const any_type& to_type = resolve_type<Tp>();
|
|
||||||
|
|
||||||
if ( from_type == to_type ) {
|
if ( from_type == to_type ) {
|
||||||
using to_ptr_t = detail::add_cv_t<V, Tp>*;
|
T* to_ptr = static_cast<T*>(data());
|
||||||
auto to_ptr = static_cast<to_ptr_t>(value.data());
|
return *to_ptr;
|
||||||
return static_cast<T>(*to_ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto is_a = [](const any_type& base, const any_type& derived){
|
const auto is_a = [](const any_type& base, const any_type& derived){
|
||||||
@@ -8456,12 +8325,11 @@ namespace meta_hpp
|
|||||||
const class_type& to_class = to_type.as_class();
|
const class_type& to_class = to_type.as_class();
|
||||||
const class_type& from_class = from_type.as_class();
|
const class_type& from_class = from_type.as_class();
|
||||||
|
|
||||||
using to_ptr_t = detail::add_cv_t<V, Tp>*;
|
T* to_ptr = static_cast<T*>(detail::pointer_upcast(data(), from_class, to_class));
|
||||||
auto to_ptr = static_cast<to_ptr_t>(detail::pointer_upcast(value.data(), from_class, to_class));
|
return *to_ptr;
|
||||||
return static_cast<T>(*to_ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr ( std::is_pointer_v<T> ) {
|
if constexpr ( detail::pointer_kind<T> ) {
|
||||||
if ( to_type.is_pointer() && from_type.is_nullptr() ) {
|
if ( to_type.is_pointer() && from_type.is_nullptr() ) {
|
||||||
return static_cast<T>(nullptr);
|
return static_cast<T>(nullptr);
|
||||||
}
|
}
|
||||||
@@ -8477,11 +8345,11 @@ namespace meta_hpp
|
|||||||
const any_type& from_data_type = from_type_ptr.get_data_type();
|
const any_type& from_data_type = from_type_ptr.get_data_type();
|
||||||
|
|
||||||
if ( to_type_ptr_readonly >= from_type_ptr_readonly ) {
|
if ( to_type_ptr_readonly >= from_type_ptr_readonly ) {
|
||||||
using from_data_ptr_t = detail::add_cv_t<V, void*>*;
|
void** from_data_ptr = static_cast<void**>(data());
|
||||||
auto from_data_ptr = static_cast<from_data_ptr_t>(value.data());
|
|
||||||
|
|
||||||
if ( to_data_type.is_void() || to_data_type == from_data_type ) {
|
if ( to_data_type.is_void() || to_data_type == from_data_type ) {
|
||||||
return static_cast<T>(*from_data_ptr);
|
void* to_ptr = *from_data_ptr;
|
||||||
|
return static_cast<T>(to_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( is_a(to_data_type, from_data_type) ) {
|
if ( is_a(to_data_type, from_data_type) ) {
|
||||||
@@ -8498,19 +8366,74 @@ namespace meta_hpp
|
|||||||
detail::throw_exception_with("bad value cast");
|
detail::throw_exception_with("bad value cast");
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T, detail::decay_value_kind V >
|
template < typename T >
|
||||||
[[nodiscard]] auto get_as_ref(V&& value) -> detail::add_cvref_t<V&&, T> {
|
auto uvalue::get_as() const -> std::conditional_t<detail::pointer_kind<T>, T, const T&> {
|
||||||
static_assert(!std::is_reference_v<T>);
|
static_assert(std::is_same_v<T, std::decay_t<T>>);
|
||||||
return get_as<detail::add_cvref_t<V&&, T>>(std::forward<V>(value));
|
|
||||||
|
const any_type& from_type = get_type();
|
||||||
|
const any_type& to_type = resolve_type<T>();
|
||||||
|
|
||||||
|
if ( from_type == to_type ) {
|
||||||
|
const T* to_ptr = static_cast<const T*>(data());
|
||||||
|
return *to_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto is_a = [](const any_type& base, const any_type& derived){
|
||||||
|
return (base == derived)
|
||||||
|
|| (base.is_class() && derived.is_class() && base.as_class().is_base_of(derived.as_class()));
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( is_a(to_type, from_type) ) {
|
||||||
|
const class_type& to_class = to_type.as_class();
|
||||||
|
const class_type& from_class = from_type.as_class();
|
||||||
|
|
||||||
|
const T* to_ptr = static_cast<const T*>(detail::pointer_upcast(data(), from_class, to_class));
|
||||||
|
return *to_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr ( detail::pointer_kind<T> ) {
|
||||||
|
if ( to_type.is_pointer() && from_type.is_nullptr() ) {
|
||||||
|
return static_cast<T>(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( to_type.is_pointer() && from_type.is_pointer() ) {
|
||||||
|
const pointer_type& to_type_ptr = to_type.as_pointer();
|
||||||
|
const bool to_type_ptr_readonly = to_type_ptr.get_flags().has(pointer_flags::is_readonly);
|
||||||
|
|
||||||
|
const pointer_type& from_type_ptr = from_type.as_pointer();
|
||||||
|
const bool from_type_ptr_readonly = from_type_ptr.get_flags().has(pointer_flags::is_readonly);
|
||||||
|
|
||||||
|
const any_type& to_data_type = to_type_ptr.get_data_type();
|
||||||
|
const any_type& from_data_type = from_type_ptr.get_data_type();
|
||||||
|
|
||||||
|
if ( to_type_ptr_readonly >= from_type_ptr_readonly ) {
|
||||||
|
void* const* from_data_ptr = static_cast<void* const*>(data());
|
||||||
|
|
||||||
|
if ( to_data_type.is_void() || to_data_type == from_data_type ) {
|
||||||
|
void* to_ptr = *from_data_ptr;
|
||||||
|
return static_cast<T>(to_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( is_a(to_data_type, from_data_type) ) {
|
||||||
|
const class_type& to_data_class = to_data_type.as_class();
|
||||||
|
const class_type& from_data_class = from_data_type.as_class();
|
||||||
|
|
||||||
|
void* to_ptr = detail::pointer_upcast(*from_data_ptr, from_data_class, to_data_class);
|
||||||
|
return static_cast<T>(to_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
detail::throw_exception_with("bad value cast");
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T, detail::decay_value_kind V >
|
template < typename T >
|
||||||
[[nodiscard]] bool can_get_as(V&& value) noexcept {
|
bool uvalue::can_get_as() const noexcept {
|
||||||
using Tp = std::decay_t<T>;
|
static_assert(std::is_same_v<T, std::decay_t<T>>);
|
||||||
static_assert(std::is_constructible_v<T, detail::add_cvref_t<V&&, Tp>>);
|
|
||||||
|
|
||||||
const any_type& from_type = value.get_type();
|
const any_type& from_type = get_type();
|
||||||
const any_type& to_type = resolve_type<Tp>();
|
const any_type& to_type = resolve_type<T>();
|
||||||
|
|
||||||
if ( from_type == to_type ) {
|
if ( from_type == to_type ) {
|
||||||
return true;
|
return true;
|
||||||
@@ -8525,7 +8448,7 @@ namespace meta_hpp
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr ( std::is_pointer_v<T> ) {
|
if constexpr ( detail::pointer_kind<T> ) {
|
||||||
if ( to_type.is_pointer() && from_type.is_nullptr() ) {
|
if ( to_type.is_pointer() && from_type.is_nullptr() ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -8550,12 +8473,6 @@ namespace meta_hpp
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T, detail::decay_value_kind V >
|
|
||||||
[[nodiscard]] bool can_get_as_ref(V&& value) noexcept {
|
|
||||||
static_assert(!std::is_reference_v<T>);
|
|
||||||
return can_get_as<detail::add_cvref_t<V&&, T>>(std::forward<V>(value));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace meta_hpp
|
namespace meta_hpp
|
||||||
@@ -8569,7 +8486,7 @@ namespace meta_hpp
|
|||||||
const any_type& l_type = l.get_type();
|
const any_type& l_type = l.get_type();
|
||||||
const any_type& r_type = resolve_type<T>();
|
const any_type& r_type = resolve_type<T>();
|
||||||
|
|
||||||
return (l_type < r_type) || (l_type == r_type && l.get_as_ref<T>() < r);
|
return (l_type < r_type) || (l_type == r_type && l.get_as<T>() < r);
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
@@ -8581,7 +8498,7 @@ namespace meta_hpp
|
|||||||
const any_type& l_type = resolve_type<T>();
|
const any_type& l_type = resolve_type<T>();
|
||||||
const any_type& r_type = r.get_type();
|
const any_type& r_type = r.get_type();
|
||||||
|
|
||||||
return (l_type < r_type) || (l_type == r_type && l < r.get_as_ref<T>());
|
return (l_type < r_type) || (l_type == r_type && l < r.get_as<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline bool operator<(const uvalue& l, const uvalue& r) {
|
[[nodiscard]] inline bool operator<(const uvalue& l, const uvalue& r) {
|
||||||
@@ -8611,7 +8528,7 @@ namespace meta_hpp
|
|||||||
const any_type& l_type = l.get_type();
|
const any_type& l_type = l.get_type();
|
||||||
const any_type& r_type = resolve_type<T>();
|
const any_type& r_type = resolve_type<T>();
|
||||||
|
|
||||||
return l_type == r_type && l.get_as_ref<T>() == r;
|
return l_type == r_type && l.get_as<T>() == r;
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
@@ -8623,7 +8540,7 @@ namespace meta_hpp
|
|||||||
const any_type& l_type = resolve_type<T>();
|
const any_type& l_type = resolve_type<T>();
|
||||||
const any_type& r_type = r.get_type();
|
const any_type& r_type = r.get_type();
|
||||||
|
|
||||||
return l_type == r_type && l == r.get_as_ref<T>();
|
return l_type == r_type && l == r.get_as<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline bool operator==(const uvalue& l, const uvalue& r) {
|
[[nodiscard]] inline bool operator==(const uvalue& l, const uvalue& r) {
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ TEST_CASE("meta/meta_features/diamond") {
|
|||||||
CHECK_FALSE(a_inst.can_cast_to<D&>());
|
CHECK_FALSE(a_inst.can_cast_to<D&>());
|
||||||
CHECK_FALSE(a_inst.can_cast_to<E&>());
|
CHECK_FALSE(a_inst.can_cast_to<E&>());
|
||||||
|
|
||||||
CHECK(&a_inst.cast<A&>() == &a_val.get_as_ref<A>());
|
CHECK(&a_inst.cast<A&>() == &a_val.get_as<A>());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
meta::uvalue b_val{B{}};
|
meta::uvalue b_val{B{}};
|
||||||
@@ -265,10 +265,10 @@ TEST_CASE("meta/meta_features/diamond") {
|
|||||||
CHECK_FALSE(b_inst.can_cast_to<D&>());
|
CHECK_FALSE(b_inst.can_cast_to<D&>());
|
||||||
CHECK_FALSE(b_inst.can_cast_to<E&>());
|
CHECK_FALSE(b_inst.can_cast_to<E&>());
|
||||||
|
|
||||||
CHECK(&b_inst.cast<A&>() == &b_val.get_as_ref<B>());
|
CHECK(&b_inst.cast<A&>() == &b_val.get_as<B>());
|
||||||
CHECK(&b_inst.cast<B&>() == &b_val.get_as_ref<B>());
|
CHECK(&b_inst.cast<B&>() == &b_val.get_as<B>());
|
||||||
|
|
||||||
CHECK(&b_inst.cast<A&>() == &b_val.get_as_ref<B>());
|
CHECK(&b_inst.cast<A&>() == &b_val.get_as<B>());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
meta::uvalue c_val{C{}};
|
meta::uvalue c_val{C{}};
|
||||||
@@ -280,8 +280,8 @@ TEST_CASE("meta/meta_features/diamond") {
|
|||||||
CHECK_FALSE(c_inst.can_cast_to<D&>());
|
CHECK_FALSE(c_inst.can_cast_to<D&>());
|
||||||
CHECK_FALSE(c_inst.can_cast_to<E&>());
|
CHECK_FALSE(c_inst.can_cast_to<E&>());
|
||||||
|
|
||||||
CHECK(&c_inst.cast<A&>() == &c_val.get_as_ref<C>());
|
CHECK(&c_inst.cast<A&>() == &c_val.get_as<C>());
|
||||||
CHECK(&c_inst.cast<C&>() == &c_val.get_as_ref<C>());
|
CHECK(&c_inst.cast<C&>() == &c_val.get_as<C>());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
meta::uvalue d_val{D{}};
|
meta::uvalue d_val{D{}};
|
||||||
@@ -293,15 +293,15 @@ TEST_CASE("meta/meta_features/diamond") {
|
|||||||
CHECK(d_inst.can_cast_to<D&>());
|
CHECK(d_inst.can_cast_to<D&>());
|
||||||
CHECK_FALSE(d_inst.can_cast_to<E&>());
|
CHECK_FALSE(d_inst.can_cast_to<E&>());
|
||||||
|
|
||||||
CHECK(&d_inst.cast<A&>() == &d_val.get_as_ref<D>());
|
CHECK(&d_inst.cast<A&>() == &d_val.get_as<D>());
|
||||||
CHECK(&d_inst.cast<B&>() == &d_val.get_as_ref<D>());
|
CHECK(&d_inst.cast<B&>() == &d_val.get_as<D>());
|
||||||
CHECK(&d_inst.cast<C&>() == &d_val.get_as_ref<D>());
|
CHECK(&d_inst.cast<C&>() == &d_val.get_as<D>());
|
||||||
CHECK(&d_inst.cast<D&>() == &d_val.get_as_ref<D>());
|
CHECK(&d_inst.cast<D&>() == &d_val.get_as<D>());
|
||||||
|
|
||||||
CHECK(&d_inst.cast<A&>() == &d_val.get_as_ref<D>());
|
CHECK(&d_inst.cast<A&>() == &d_val.get_as<D>());
|
||||||
CHECK(&d_inst.cast<B&>() == &d_val.get_as_ref<D>());
|
CHECK(&d_inst.cast<B&>() == &d_val.get_as<D>());
|
||||||
CHECK(&d_inst.cast<C&>() == &d_val.get_as_ref<D>());
|
CHECK(&d_inst.cast<C&>() == &d_val.get_as<D>());
|
||||||
CHECK(&d_inst.cast<D&>() == &d_val.get_as_ref<D>());
|
CHECK(&d_inst.cast<D&>() == &d_val.get_as<D>());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
meta::uvalue e_val{E{}};
|
meta::uvalue e_val{E{}};
|
||||||
@@ -313,7 +313,7 @@ TEST_CASE("meta/meta_features/diamond") {
|
|||||||
CHECK_FALSE(e_inst.can_cast_to<D&>());
|
CHECK_FALSE(e_inst.can_cast_to<D&>());
|
||||||
CHECK(e_inst.can_cast_to<E&>());
|
CHECK(e_inst.can_cast_to<E&>());
|
||||||
|
|
||||||
CHECK(&e_inst.cast<E&>() == &e_val.get_as_ref<E>());
|
CHECK(&e_inst.cast<E&>() == &e_val.get_as<E>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ TEST_CASE("meta/meta_states/ctor") {
|
|||||||
CHECK_FALSE(clazz_type.create(10, 20));
|
CHECK_FALSE(clazz_type.create(10, 20));
|
||||||
const meta::uvalue v = clazz_type.create(10);
|
const meta::uvalue v = clazz_type.create(10);
|
||||||
CHECK(v.get_type() == meta::resolve_type<clazz<1>>());
|
CHECK(v.get_type() == meta::resolve_type<clazz<1>>());
|
||||||
CHECK(v.get_as_ref<clazz<1>>().i == 10);
|
CHECK(v.get_as<clazz<1>>().i == 10);
|
||||||
|
|
||||||
CHECK(clazz_type.destroy(nullptr));
|
CHECK(clazz_type.destroy(nullptr));
|
||||||
CHECK(clazz_type.destroy(meta::uvalue{nullptr}));
|
CHECK(clazz_type.destroy(meta::uvalue{nullptr}));
|
||||||
@@ -112,7 +112,7 @@ TEST_CASE("meta/meta_states/ctor") {
|
|||||||
CHECK_FALSE(clazz_type.create(10, 20));
|
CHECK_FALSE(clazz_type.create(10, 20));
|
||||||
const meta::uvalue v = clazz_type.create(20);
|
const meta::uvalue v = clazz_type.create(20);
|
||||||
CHECK(v.get_type() == meta::resolve_type<clazz<2>*>());
|
CHECK(v.get_type() == meta::resolve_type<clazz<2>*>());
|
||||||
CHECK(v.get_as_ref<clazz<2>*>()->i == 20);
|
CHECK(v.get_as<clazz<2>*>()->i == 20);
|
||||||
CHECK(clazz_type.destroy(v));
|
CHECK(clazz_type.destroy(v));
|
||||||
|
|
||||||
CHECK(clazz_type.destroy(nullptr));
|
CHECK(clazz_type.destroy(nullptr));
|
||||||
@@ -133,7 +133,7 @@ TEST_CASE("meta/meta_states/ctor") {
|
|||||||
CHECK_FALSE(clazz_type.create(10, 20));
|
CHECK_FALSE(clazz_type.create(10, 20));
|
||||||
const meta::uvalue v = clazz_type.create(30);
|
const meta::uvalue v = clazz_type.create(30);
|
||||||
CHECK(v.get_type() == meta::resolve_type<std::shared_ptr<clazz<3>>>());
|
CHECK(v.get_type() == meta::resolve_type<std::shared_ptr<clazz<3>>>());
|
||||||
CHECK(v.get_as_ref<std::shared_ptr<clazz<3>>>()->i == 30);
|
CHECK(v.get_as<std::shared_ptr<clazz<3>>>()->i == 30);
|
||||||
|
|
||||||
CHECK(clazz_type.destroy(nullptr));
|
CHECK(clazz_type.destroy(nullptr));
|
||||||
CHECK(clazz_type.destroy(meta::uvalue{nullptr}));
|
CHECK(clazz_type.destroy(meta::uvalue{nullptr}));
|
||||||
|
|||||||
@@ -247,14 +247,14 @@ TEST_CASE("meta/meta_states/member") {
|
|||||||
clazz_1 v;
|
clazz_1 v;
|
||||||
using ref_t = std::reference_wrapper<std::unique_ptr<int>>;
|
using ref_t = std::reference_wrapper<std::unique_ptr<int>>;
|
||||||
CHECK(vm.get(v).get_type() == meta::resolve_type<ref_t>());
|
CHECK(vm.get(v).get_type() == meta::resolve_type<ref_t>());
|
||||||
CHECK(vm.get(v).get_as_ref<ref_t>().get() == v.unique_int_member);
|
CHECK(vm.get(v).get_as<ref_t>().get() == v.unique_int_member);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const clazz_1 v;
|
const clazz_1 v;
|
||||||
using ref_t = std::reference_wrapper<const std::unique_ptr<int>>;
|
using ref_t = std::reference_wrapper<const std::unique_ptr<int>>;
|
||||||
CHECK(vm.get(v).get_type() == meta::resolve_type<ref_t>());
|
CHECK(vm.get(v).get_type() == meta::resolve_type<ref_t>());
|
||||||
CHECK(vm.get(v).get_as_ref<ref_t>().get() == v.unique_int_member);
|
CHECK(vm.get(v).get_as<ref_t>().get() == v.unique_int_member);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ TEST_CASE("meta/meta_states/variable") {
|
|||||||
|
|
||||||
using ref_t = std::reference_wrapper<std::unique_ptr<int>>;
|
using ref_t = std::reference_wrapper<std::unique_ptr<int>>;
|
||||||
CHECK(vm.get().get_type() == meta::resolve_type<ref_t>());
|
CHECK(vm.get().get_type() == meta::resolve_type<ref_t>());
|
||||||
CHECK(vm.get().get_as_ref<ref_t>().get() == clazz_1::unique_int_variable);
|
CHECK(vm.get().get_as<ref_t>().get() == clazz_1::unique_int_variable);
|
||||||
|
|
||||||
{
|
{
|
||||||
auto nv = std::make_unique<int>(13);
|
auto nv = std::make_unique<int>(13);
|
||||||
@@ -222,7 +222,7 @@ TEST_CASE("meta/meta_states/variable") {
|
|||||||
|
|
||||||
using ref_t = std::reference_wrapper<const std::unique_ptr<int>>;
|
using ref_t = std::reference_wrapper<const std::unique_ptr<int>>;
|
||||||
CHECK(vm.get().get_type() == meta::resolve_type<ref_t>());
|
CHECK(vm.get().get_type() == meta::resolve_type<ref_t>());
|
||||||
CHECK(vm.get().get_as_ref<ref_t>().get() == clazz_1::const_unique_int_variable);
|
CHECK(vm.get().get_as<ref_t>().get() == clazz_1::const_unique_int_variable);
|
||||||
|
|
||||||
{
|
{
|
||||||
auto nv = std::make_unique<int>(12);
|
auto nv = std::make_unique<int>(12);
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ TEST_CASE("meta/meta_utilities/value2/counters/small") {
|
|||||||
meta::uvalue v2{std::move(v1)};
|
meta::uvalue v2{std::move(v1)};
|
||||||
|
|
||||||
CHECK_FALSE(v1);
|
CHECK_FALSE(v1);
|
||||||
CHECK(v2.get_as_ref<ivec2>().x == 1);
|
CHECK(v2.get_as<ivec2>().x == 1);
|
||||||
|
|
||||||
CHECK(ivec2::destructor_counter == 2);
|
CHECK(ivec2::destructor_counter == 2);
|
||||||
CHECK(ivec2::move_constructor_counter == 2);
|
CHECK(ivec2::move_constructor_counter == 2);
|
||||||
@@ -170,8 +170,8 @@ TEST_CASE("meta/meta_utilities/value2/counters/small") {
|
|||||||
meta::uvalue v1{ivec2{1,2}};
|
meta::uvalue v1{ivec2{1,2}};
|
||||||
meta::uvalue v2{std::as_const(v1)};
|
meta::uvalue v2{std::as_const(v1)};
|
||||||
|
|
||||||
CHECK(v1.get_as_ref<ivec2>().x == 1);
|
CHECK(v1.get_as<ivec2>().x == 1);
|
||||||
CHECK(v2.get_as_ref<ivec2>().y == 2);
|
CHECK(v2.get_as<ivec2>().y == 2);
|
||||||
|
|
||||||
CHECK(ivec2::destructor_counter == 1);
|
CHECK(ivec2::destructor_counter == 1);
|
||||||
CHECK(ivec2::move_constructor_counter == 1);
|
CHECK(ivec2::move_constructor_counter == 1);
|
||||||
@@ -191,8 +191,8 @@ TEST_CASE("meta/meta_utilities/value2/counters/small") {
|
|||||||
CHECK(ivec2::copy_constructor_counter == 0);
|
CHECK(ivec2::copy_constructor_counter == 0);
|
||||||
|
|
||||||
v1.swap(v2);
|
v1.swap(v2);
|
||||||
CHECK(v1.get_as_ref<ivec2>().x == 3);
|
CHECK(v1.get_as<ivec2>().x == 3);
|
||||||
CHECK(v2.get_as_ref<ivec2>().x == 1);
|
CHECK(v2.get_as<ivec2>().x == 1);
|
||||||
|
|
||||||
CHECK(ivec2::destructor_counter == 5);
|
CHECK(ivec2::destructor_counter == 5);
|
||||||
CHECK(ivec2::move_constructor_counter == 5);
|
CHECK(ivec2::move_constructor_counter == 5);
|
||||||
@@ -241,7 +241,7 @@ TEST_CASE("meta/meta_utilities/value2/counters/big") {
|
|||||||
meta::uvalue v2{std::move(v1)};
|
meta::uvalue v2{std::move(v1)};
|
||||||
|
|
||||||
CHECK_FALSE(v1);
|
CHECK_FALSE(v1);
|
||||||
CHECK(v2.get_as_ref<ivec2_big>().x == 1);
|
CHECK(v2.get_as<ivec2_big>().x == 1);
|
||||||
|
|
||||||
CHECK(ivec2_big::destructor_counter == 1);
|
CHECK(ivec2_big::destructor_counter == 1);
|
||||||
CHECK(ivec2_big::move_constructor_counter == 1);
|
CHECK(ivec2_big::move_constructor_counter == 1);
|
||||||
@@ -257,8 +257,8 @@ TEST_CASE("meta/meta_utilities/value2/counters/big") {
|
|||||||
meta::uvalue v1{ivec2_big{1,2}};
|
meta::uvalue v1{ivec2_big{1,2}};
|
||||||
meta::uvalue v2{std::as_const(v1)};
|
meta::uvalue v2{std::as_const(v1)};
|
||||||
|
|
||||||
CHECK(v1.get_as_ref<ivec2_big>().x == 1);
|
CHECK(v1.get_as<ivec2_big>().x == 1);
|
||||||
CHECK(v2.get_as_ref<ivec2_big>().y == 2);
|
CHECK(v2.get_as<ivec2_big>().y == 2);
|
||||||
|
|
||||||
CHECK(ivec2_big::destructor_counter == 1);
|
CHECK(ivec2_big::destructor_counter == 1);
|
||||||
CHECK(ivec2_big::move_constructor_counter == 1);
|
CHECK(ivec2_big::move_constructor_counter == 1);
|
||||||
@@ -278,8 +278,8 @@ TEST_CASE("meta/meta_utilities/value2/counters/big") {
|
|||||||
CHECK(ivec2_big::copy_constructor_counter == 0);
|
CHECK(ivec2_big::copy_constructor_counter == 0);
|
||||||
|
|
||||||
v1.swap(v2);
|
v1.swap(v2);
|
||||||
CHECK(v1.get_as_ref<ivec2_big>().x == 3);
|
CHECK(v1.get_as<ivec2_big>().x == 3);
|
||||||
CHECK(v2.get_as_ref<ivec2_big>().x == 1);
|
CHECK(v2.get_as<ivec2_big>().x == 1);
|
||||||
|
|
||||||
CHECK(ivec2_big::destructor_counter == 2);
|
CHECK(ivec2_big::destructor_counter == 2);
|
||||||
CHECK(ivec2_big::move_constructor_counter == 2);
|
CHECK(ivec2_big::move_constructor_counter == 2);
|
||||||
@@ -312,7 +312,7 @@ TEST_CASE("meta/meta_utilities/value2/counters/swap") {
|
|||||||
CHECK(ivec2::copy_constructor_counter == 0);
|
CHECK(ivec2::copy_constructor_counter == 0);
|
||||||
|
|
||||||
v1.swap(v2);
|
v1.swap(v2);
|
||||||
CHECK(v1.get_as_ref<ivec2>().x == 1);
|
CHECK(v1.get_as<ivec2>().x == 1);
|
||||||
CHECK_FALSE(v2);
|
CHECK_FALSE(v2);
|
||||||
|
|
||||||
CHECK(ivec2::destructor_counter == 2);
|
CHECK(ivec2::destructor_counter == 2);
|
||||||
@@ -321,7 +321,7 @@ TEST_CASE("meta/meta_utilities/value2/counters/swap") {
|
|||||||
|
|
||||||
v1.swap(v2);
|
v1.swap(v2);
|
||||||
CHECK_FALSE(v1);
|
CHECK_FALSE(v1);
|
||||||
CHECK(v2.get_as_ref<ivec2>().y == 2);
|
CHECK(v2.get_as<ivec2>().y == 2);
|
||||||
|
|
||||||
CHECK(ivec2::destructor_counter == 3);
|
CHECK(ivec2::destructor_counter == 3);
|
||||||
CHECK(ivec2::move_constructor_counter == 3);
|
CHECK(ivec2::move_constructor_counter == 3);
|
||||||
@@ -343,7 +343,7 @@ TEST_CASE("meta/meta_utilities/value2/counters/swap") {
|
|||||||
CHECK(ivec2_big::copy_constructor_counter == 0);
|
CHECK(ivec2_big::copy_constructor_counter == 0);
|
||||||
|
|
||||||
v1.swap(v2);
|
v1.swap(v2);
|
||||||
CHECK(v1.get_as_ref<ivec2_big>().x == 3);
|
CHECK(v1.get_as<ivec2_big>().x == 3);
|
||||||
CHECK_FALSE(v2);
|
CHECK_FALSE(v2);
|
||||||
|
|
||||||
CHECK(ivec2_big::destructor_counter == 1);
|
CHECK(ivec2_big::destructor_counter == 1);
|
||||||
@@ -352,7 +352,7 @@ TEST_CASE("meta/meta_utilities/value2/counters/swap") {
|
|||||||
|
|
||||||
v1.swap(v2);
|
v1.swap(v2);
|
||||||
CHECK_FALSE(v1);
|
CHECK_FALSE(v1);
|
||||||
CHECK(v2.get_as_ref<ivec2_big>().y == 4);
|
CHECK(v2.get_as<ivec2_big>().y == 4);
|
||||||
|
|
||||||
CHECK(ivec2_big::destructor_counter == 1);
|
CHECK(ivec2_big::destructor_counter == 1);
|
||||||
CHECK(ivec2_big::move_constructor_counter == 1);
|
CHECK(ivec2_big::move_constructor_counter == 1);
|
||||||
@@ -378,8 +378,8 @@ TEST_CASE("meta/meta_utilities/value2/counters/swap") {
|
|||||||
CHECK(ivec2_big::copy_constructor_counter == 0);
|
CHECK(ivec2_big::copy_constructor_counter == 0);
|
||||||
|
|
||||||
v1.swap(v2);
|
v1.swap(v2);
|
||||||
CHECK(v1.get_as_ref<ivec2_big>().x == 3);
|
CHECK(v1.get_as<ivec2_big>().x == 3);
|
||||||
CHECK(v2.get_as_ref<ivec2>().x == 1);
|
CHECK(v2.get_as<ivec2>().x == 1);
|
||||||
|
|
||||||
CHECK(ivec2::destructor_counter == 2);
|
CHECK(ivec2::destructor_counter == 2);
|
||||||
CHECK(ivec2::move_constructor_counter == 2);
|
CHECK(ivec2::move_constructor_counter == 2);
|
||||||
@@ -390,8 +390,8 @@ TEST_CASE("meta/meta_utilities/value2/counters/swap") {
|
|||||||
CHECK(ivec2_big::copy_constructor_counter == 0);
|
CHECK(ivec2_big::copy_constructor_counter == 0);
|
||||||
|
|
||||||
v1.swap(v2);
|
v1.swap(v2);
|
||||||
CHECK(v1.get_as_ref<ivec2>().y == 2);
|
CHECK(v1.get_as<ivec2>().y == 2);
|
||||||
CHECK(v2.get_as_ref<ivec2_big>().y == 4);
|
CHECK(v2.get_as<ivec2_big>().y == 4);
|
||||||
|
|
||||||
CHECK(ivec2::destructor_counter == 3);
|
CHECK(ivec2::destructor_counter == 3);
|
||||||
CHECK(ivec2::move_constructor_counter == 3);
|
CHECK(ivec2::move_constructor_counter == 3);
|
||||||
|
|||||||
@@ -95,126 +95,63 @@ TEST_CASE("meta/meta_utilities/value4/get_type") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("meta/meta_utilities/value4/get_as_ref") {
|
|
||||||
namespace meta = meta_hpp;
|
|
||||||
|
|
||||||
static_assert(std::is_same_v<decltype(get_as_ref<derived>(std::declval<meta::uvalue&>())), derived&>);
|
|
||||||
static_assert(std::is_same_v<decltype(get_as_ref<derived>(std::declval<meta::uvalue&&>())), derived&&>);
|
|
||||||
static_assert(std::is_same_v<decltype(get_as_ref<derived>(std::declval<const meta::uvalue&>())), const derived&>);
|
|
||||||
static_assert(std::is_same_v<decltype(get_as_ref<derived>(std::declval<const meta::uvalue&&>())), const derived&&>);
|
|
||||||
|
|
||||||
static_assert(std::is_same_v<decltype(get_as_ref<const derived>(std::declval<meta::uvalue&>())), const derived&>);
|
|
||||||
static_assert(std::is_same_v<decltype(get_as_ref<const derived>(std::declval<meta::uvalue&&>())), const derived&&>);
|
|
||||||
static_assert(std::is_same_v<decltype(get_as_ref<const derived>(std::declval<const meta::uvalue&>())), const derived&>);
|
|
||||||
static_assert(std::is_same_v<decltype(get_as_ref<const derived>(std::declval<const meta::uvalue&&>())), const derived&&>);
|
|
||||||
|
|
||||||
static_assert(std::is_same_v<decltype(get_as_ref<volatile derived>(std::declval<meta::uvalue&>())), volatile derived&>);
|
|
||||||
static_assert(std::is_same_v<decltype(get_as_ref<volatile derived>(std::declval<meta::uvalue&&>())), volatile derived&&>);
|
|
||||||
static_assert(std::is_same_v<decltype(get_as_ref<volatile derived>(std::declval<const meta::uvalue&>())), const volatile derived&>);
|
|
||||||
static_assert(std::is_same_v<decltype(get_as_ref<volatile derived>(std::declval<const meta::uvalue&&>())), const volatile derived&&>);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("meta/meta_utilities/value4/get_as") {
|
TEST_CASE("meta/meta_utilities/value4/get_as") {
|
||||||
namespace meta = meta_hpp;
|
namespace meta = meta_hpp;
|
||||||
|
|
||||||
static_assert(std::is_same_v<decltype(get_as<derived>(std::declval<meta::uvalue&>())), derived>);
|
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&>().get_as<derived>()), derived&>);
|
||||||
static_assert(std::is_same_v<decltype(get_as<derived>(std::declval<meta::uvalue&&>())), derived>);
|
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&&>().get_as<derived>()), derived&>);
|
||||||
static_assert(std::is_same_v<decltype(get_as<derived>(std::declval<const meta::uvalue&>())), derived>);
|
static_assert(std::is_same_v<decltype(std::declval<const meta::uvalue&>().get_as<derived>()), const derived&>);
|
||||||
static_assert(std::is_same_v<decltype(get_as<derived>(std::declval<const meta::uvalue&&>())), derived>);
|
static_assert(std::is_same_v<decltype(std::declval<const meta::uvalue&&>().get_as<derived>()), const derived&>);
|
||||||
|
|
||||||
static_assert(std::is_same_v<decltype(get_as<derived&>(std::declval<meta::uvalue&>())), derived&>);
|
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&>().get_as<derived*>()), derived*>);
|
||||||
static_assert(std::is_same_v<decltype(get_as<derived&>(std::declval<meta::uvalue&&>())), derived&>);
|
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&&>().get_as<derived*>()), derived*>);
|
||||||
static_assert(std::is_same_v<decltype(get_as<derived&>(std::declval<const meta::uvalue&>())), derived&>);
|
static_assert(std::is_same_v<decltype(std::declval<const meta::uvalue&>().get_as<derived*>()), derived*>);
|
||||||
static_assert(std::is_same_v<decltype(get_as<derived&>(std::declval<const meta::uvalue&&>())), derived&>);
|
static_assert(std::is_same_v<decltype(std::declval<const meta::uvalue&&>().get_as<derived*>()), derived*>);
|
||||||
|
|
||||||
static_assert(std::is_same_v<decltype(get_as<const derived&>(std::declval<meta::uvalue&>())), const derived&>);
|
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&>().get_as<const derived*>()), const derived*>);
|
||||||
static_assert(std::is_same_v<decltype(get_as<const derived&>(std::declval<meta::uvalue&&>())), const derived&>);
|
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&&>().get_as<const derived*>()), const derived*>);
|
||||||
static_assert(std::is_same_v<decltype(get_as<const derived&>(std::declval<const meta::uvalue&>())), const derived&>);
|
static_assert(std::is_same_v<decltype(std::declval<const meta::uvalue&>().get_as<const derived*>()), const derived*>);
|
||||||
static_assert(std::is_same_v<decltype(get_as<const derived&>(std::declval<const meta::uvalue&&>())), const derived&>);
|
static_assert(std::is_same_v<decltype(std::declval<const meta::uvalue&&>().get_as<const derived*>()), const derived*>);
|
||||||
|
|
||||||
SUBCASE("derived to derived") {
|
SUBCASE("derived to derived") {
|
||||||
{
|
{
|
||||||
meta::uvalue v{derived{}};
|
meta::uvalue v{derived{}};
|
||||||
CHECK(get_as<derived>(v).l == 168);
|
CHECK(v.get_as<derived>().l == 168);
|
||||||
CHECK(get_as<derived&>(v).l == 168);
|
CHECK_THROWS(std::ignore = v.get_as<derived2>());
|
||||||
// CHECK(get_as<derived&&>(v).l == 168);
|
|
||||||
CHECK(get_as<const derived&>(v).l == 168);
|
|
||||||
// CHECK(get_as<const derived&&>(v).l == 168);
|
|
||||||
|
|
||||||
CHECK_THROWS(std::ignore = get_as<derived2>(v));
|
|
||||||
CHECK_THROWS(std::ignore = get_as<derived2&>(v));
|
|
||||||
CHECK_THROWS(std::ignore = get_as<const derived2&>(v));
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
meta::uvalue v{derived{}};
|
meta::uvalue v{derived{}};
|
||||||
CHECK(get_as<derived>(std::move(v)).l == 168);
|
CHECK(std::move(v).get_as<derived>().l == 168);
|
||||||
// CHECK(get_as<derived&>(std::move(v)).l == 168);
|
CHECK_THROWS(std::ignore = std::move(v).get_as<derived2>());
|
||||||
CHECK(get_as<derived&&>(std::move(v)).l == 168);
|
|
||||||
CHECK(get_as<const derived&>(std::move(v)).l == 168);
|
|
||||||
CHECK(get_as<const derived&&>(std::move(v)).l == 168);
|
|
||||||
|
|
||||||
CHECK_THROWS(std::ignore = get_as<derived2>(std::move(v)));
|
|
||||||
CHECK_THROWS(std::ignore = get_as<derived2&&>(std::move(v)));
|
|
||||||
CHECK_THROWS(std::ignore = get_as<const derived2&>(std::move(v)));
|
|
||||||
CHECK_THROWS(std::ignore = get_as<const derived2&&>(std::move(v)));
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const meta::uvalue v{derived{}};
|
const meta::uvalue v{derived{}};
|
||||||
CHECK(get_as<derived>(v).l == 168);
|
CHECK(v.get_as<derived>().l == 168);
|
||||||
// CHECK(get_as<derived&>(v).l == 168);
|
CHECK_THROWS(std::ignore = v.get_as<derived2>());
|
||||||
// CHECK(get_as<derived&&>(v).l == 168);
|
|
||||||
CHECK(get_as<const derived&>(v).l == 168);
|
|
||||||
// CHECK(get_as<const derived&&>(v).l == 168);
|
|
||||||
|
|
||||||
CHECK_THROWS(std::ignore = get_as<derived2>(v));
|
|
||||||
CHECK_THROWS(std::ignore = get_as<const derived2&>(v));
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const meta::uvalue v{derived{}};
|
const meta::uvalue v{derived{}};
|
||||||
CHECK(get_as<derived>(std::move(v)).l == 168);
|
CHECK(std::move(v).get_as<derived>().l == 168);
|
||||||
// CHECK(get_as<derived&>(std::move(v)).l == 168);
|
CHECK_THROWS(std::ignore = std::move(v).get_as<derived2>());
|
||||||
// CHECK(get_as<derived&&>(std::move(v)).l == 168);
|
|
||||||
CHECK(get_as<const derived&>(std::move(v)).l == 168);
|
|
||||||
CHECK(get_as<const derived&&>(std::move(v)).l == 168);
|
|
||||||
|
|
||||||
CHECK_THROWS(std::ignore = get_as<derived2>(std::move(v)));
|
|
||||||
CHECK_THROWS(std::ignore = get_as<const derived2&>(std::move(v)));
|
|
||||||
CHECK_THROWS(std::ignore = get_as<const derived2&&>(std::move(v)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBCASE("derived to base") {
|
SUBCASE("derived to base") {
|
||||||
{
|
{
|
||||||
meta::uvalue v{derived{}};
|
meta::uvalue v{derived{}};
|
||||||
CHECK(get_as<base2>(v).k == 84);
|
CHECK(v.get_as<base2>().k == 84);
|
||||||
CHECK(get_as<base2&>(v).k == 84);
|
|
||||||
// CHECK(get_as<base2&&>(v).k == 84);
|
|
||||||
CHECK(get_as<const base2&>(v).k == 84);
|
|
||||||
// CHECK(get_as<const base2&&>(v).k == 84);
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
meta::uvalue v{derived{}};
|
meta::uvalue v{derived{}};
|
||||||
CHECK(get_as<base2>(std::move(v)).k == 84);
|
CHECK(std::move(v).get_as<base2>().k == 84);
|
||||||
// CHECK(get_as<base2&>(std::move(v)).k == 84);
|
|
||||||
CHECK(get_as<base2&&>(std::move(v)).k == 84);
|
|
||||||
CHECK(get_as<const base2&>(std::move(v)).k == 84);
|
|
||||||
CHECK(get_as<const base2&&>(std::move(v)).k == 84);
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const meta::uvalue v{derived{}};
|
const meta::uvalue v{derived{}};
|
||||||
CHECK(get_as<base2>(v).k == 84);
|
CHECK(v.get_as<base2>().k == 84);
|
||||||
// CHECK(get_as<base2&>(v).k == 84);
|
|
||||||
// CHECK(get_as<base2&&>(v).k == 84);
|
|
||||||
CHECK(get_as<const base2&>(v).k == 84);
|
|
||||||
// CHECK(get_as<const base2&&>(v).k == 84);
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const meta::uvalue v{derived{}};
|
const meta::uvalue v{derived{}};
|
||||||
CHECK(get_as<base2>(std::move(v)).k == 84);
|
CHECK(std::move(v).get_as<base2>().k == 84);
|
||||||
// CHECK(get_as<base2&>(std::move(v)).k == 84);
|
|
||||||
// CHECK(get_as<base2&&>(std::move(v)).k == 84);
|
|
||||||
CHECK(get_as<const base2&>(std::move(v)).k == 84);
|
|
||||||
CHECK(get_as<const base2&&>(std::move(v)).k == 84);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,43 +159,43 @@ TEST_CASE("meta/meta_utilities/value4/get_as") {
|
|||||||
{
|
{
|
||||||
derived d{};
|
derived d{};
|
||||||
meta::uvalue v{&d};
|
meta::uvalue v{&d};
|
||||||
CHECK(get_as<void*>(v) == &d);
|
CHECK(v.get_as<void*>() == &d);
|
||||||
CHECK(get_as<const void*>(v) == &d);
|
CHECK(v.get_as<const void*>() == &d);
|
||||||
CHECK(get_as<void*>(std::move(v)) == &d);
|
CHECK(std::move(v).get_as<void*>() == &d);
|
||||||
CHECK(get_as<const void*>(std::move(v)) == &d);
|
CHECK(std::move(v).get_as<const void*>() == &d);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const derived d{};
|
const derived d{};
|
||||||
meta::uvalue v{&d};
|
meta::uvalue v{&d};
|
||||||
CHECK_THROWS(std::ignore = get_as<void*>(v));
|
CHECK_THROWS(std::ignore = v.get_as<void*>());
|
||||||
CHECK(get_as<const void*>(v) == &d);
|
CHECK(v.get_as<const void*>() == &d);
|
||||||
CHECK_THROWS(std::ignore = get_as<void*>(std::move(v)));
|
CHECK_THROWS(std::ignore = std::move(v).get_as<void*>());
|
||||||
CHECK(get_as<const void*>(std::move(v)) == &d);
|
CHECK(std::move(v).get_as<const void*>() == &d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBCASE("nullptr") {
|
SUBCASE("nullptr") {
|
||||||
{
|
{
|
||||||
meta::uvalue v{nullptr};
|
meta::uvalue v{nullptr};
|
||||||
CHECK(get_as<void*>(v) == nullptr);
|
CHECK(v.get_as<void*>() == nullptr);
|
||||||
CHECK(get_as<const void*>(v) == nullptr);
|
CHECK(v.get_as<const void*>() == nullptr);
|
||||||
CHECK(get_as<derived*>(v) == nullptr);
|
CHECK(v.get_as<derived*>() == nullptr);
|
||||||
CHECK(get_as<const derived*>(v) == nullptr);
|
CHECK(v.get_as<const derived*>() == nullptr);
|
||||||
CHECK(get_as<void*>(std::move(v)) == nullptr);
|
CHECK(std::move(v).get_as<void*>() == nullptr);
|
||||||
CHECK(get_as<const void*>(std::move(v)) == nullptr);
|
CHECK(std::move(v).get_as<const void*>() == nullptr);
|
||||||
CHECK(get_as<derived*>(std::move(v)) == nullptr);
|
CHECK(std::move(v).get_as<derived*>() == nullptr);
|
||||||
CHECK(get_as<const derived*>(std::move(v)) == nullptr);
|
CHECK(std::move(v).get_as<const derived*>() == nullptr);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const meta::uvalue v{nullptr};
|
const meta::uvalue v{nullptr};
|
||||||
CHECK(get_as<void*>(v) == nullptr);
|
CHECK(v.get_as<void*>() == nullptr);
|
||||||
CHECK(get_as<const void*>(v) == nullptr);
|
CHECK(v.get_as<const void*>() == nullptr);
|
||||||
CHECK(get_as<derived*>(v) == nullptr);
|
CHECK(v.get_as<derived*>() == nullptr);
|
||||||
CHECK(get_as<const derived*>(v) == nullptr);
|
CHECK(v.get_as<const derived*>() == nullptr);
|
||||||
CHECK(get_as<void*>(std::move(v)) == nullptr);
|
CHECK(std::move(v).get_as<void*>() == nullptr);
|
||||||
CHECK(get_as<const void*>(std::move(v)) == nullptr);
|
CHECK(std::move(v).get_as<const void*>() == nullptr);
|
||||||
CHECK(get_as<derived*>(std::move(v)) == nullptr);
|
CHECK(std::move(v).get_as<derived*>() == nullptr);
|
||||||
CHECK(get_as<const derived*>(std::move(v)) == nullptr);
|
CHECK(std::move(v).get_as<const derived*>() == nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,34 +203,34 @@ TEST_CASE("meta/meta_utilities/value4/get_as") {
|
|||||||
{
|
{
|
||||||
derived d{};
|
derived d{};
|
||||||
meta::uvalue v{&d};
|
meta::uvalue v{&d};
|
||||||
CHECK(get_as<derived*>(v)->l == 168);
|
CHECK(v.get_as<derived*>()->l == 168);
|
||||||
CHECK(get_as<const derived*>(v)->l == 168);
|
CHECK(v.get_as<const derived*>()->l == 168);
|
||||||
|
|
||||||
CHECK_THROWS(std::ignore = get_as<derived2*>(v));
|
CHECK_THROWS(std::ignore = v.get_as<derived2*>());
|
||||||
CHECK_THROWS(std::ignore = get_as<const derived2*>(v));
|
CHECK_THROWS(std::ignore = v.get_as<const derived2*>());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
derived d{};
|
derived d{};
|
||||||
meta::uvalue v{&d};
|
meta::uvalue v{&d};
|
||||||
CHECK(get_as<derived*>(std::move(v))->l == 168);
|
CHECK(std::move(v).get_as<derived*>()->l == 168);
|
||||||
CHECK(get_as<const derived*>(std::move(v))->l == 168);
|
CHECK(std::move(v).get_as<const derived*>()->l == 168);
|
||||||
|
|
||||||
CHECK_THROWS(std::ignore = get_as<derived2*>(std::move(v)));
|
CHECK_THROWS(std::ignore = std::move(v).get_as<derived2*>());
|
||||||
CHECK_THROWS(std::ignore = get_as<const derived2*>(std::move(v)));
|
CHECK_THROWS(std::ignore = std::move(v).get_as<const derived2*>());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const derived d{};
|
const derived d{};
|
||||||
meta::uvalue v{&d};
|
meta::uvalue v{&d};
|
||||||
CHECK(get_as<const derived*>(v)->l == 168);
|
CHECK(v.get_as<const derived*>()->l == 168);
|
||||||
|
|
||||||
CHECK_THROWS(std::ignore = get_as<const derived2*>(v));
|
CHECK_THROWS(std::ignore = v.get_as<const derived2*>());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const derived d{};
|
const derived d{};
|
||||||
meta::uvalue v{&d};
|
meta::uvalue v{&d};
|
||||||
CHECK(get_as<const derived*>(std::move(v))->l == 168);
|
CHECK(std::move(v).get_as<const derived*>()->l == 168);
|
||||||
|
|
||||||
CHECK_THROWS(std::ignore = get_as<const derived2*>(std::move(v)));
|
CHECK_THROWS(std::ignore = std::move(v).get_as<const derived2*>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,15 +238,15 @@ TEST_CASE("meta/meta_utilities/value4/get_as") {
|
|||||||
{
|
{
|
||||||
derived d{};
|
derived d{};
|
||||||
meta::uvalue v{&d};
|
meta::uvalue v{&d};
|
||||||
CHECK(get_as<base2*>(v)->k == 84);
|
CHECK(v.get_as<base2*>()->k == 84);
|
||||||
CHECK(get_as<const base2*>(v)->k == 84);
|
CHECK(v.get_as<const base2*>()->k == 84);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const derived d{};
|
const derived d{};
|
||||||
meta::uvalue v{&d};
|
meta::uvalue v{&d};
|
||||||
CHECK_THROWS(std::ignore = get_as<base2*>(v));
|
CHECK_THROWS(std::ignore = v.get_as<base2*>());
|
||||||
CHECK(get_as<const base2*>(v)->k == 84);
|
CHECK(v.get_as<const base2*>()->k == 84);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -320,51 +257,23 @@ TEST_CASE("meta/meta_utilities/value4/can_get_as") {
|
|||||||
SUBCASE("derived to derived") {
|
SUBCASE("derived to derived") {
|
||||||
{
|
{
|
||||||
meta::uvalue v{derived{}};
|
meta::uvalue v{derived{}};
|
||||||
CHECK(can_get_as<derived>(v));
|
CHECK(v.can_get_as<derived>());
|
||||||
CHECK(can_get_as<derived&>(v));
|
CHECK_FALSE(v.can_get_as<derived2>());
|
||||||
// CHECK_FALSE(can_get_as<derived&&>(v));
|
|
||||||
CHECK(can_get_as<const derived&>(v));
|
|
||||||
// CHECK_FALSE(can_get_as<const derived&&>(v));
|
|
||||||
|
|
||||||
CHECK_FALSE(can_get_as<derived2>(v));
|
|
||||||
CHECK_FALSE(can_get_as<derived2&>(v));
|
|
||||||
CHECK_FALSE(can_get_as<const derived2&>(v));
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
meta::uvalue v{derived{}};
|
meta::uvalue v{derived{}};
|
||||||
CHECK(can_get_as<derived>(std::move(v)));
|
CHECK(std::move(v).can_get_as<derived>());
|
||||||
// CHECK_FALSE(can_get_as<derived&>(std::move(v)));
|
CHECK_FALSE(std::move(v).can_get_as<derived2>());
|
||||||
CHECK(can_get_as<derived&&>(std::move(v)));
|
|
||||||
CHECK(can_get_as<const derived&>(std::move(v)));
|
|
||||||
CHECK(can_get_as<const derived&&>(std::move(v)));
|
|
||||||
|
|
||||||
CHECK_FALSE(can_get_as<derived2>(std::move(v)));
|
|
||||||
CHECK_FALSE(can_get_as<derived2&&>(std::move(v)));
|
|
||||||
CHECK_FALSE(can_get_as<const derived2&>(std::move(v)));
|
|
||||||
CHECK_FALSE(can_get_as<const derived2&&>(std::move(v)));
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const meta::uvalue v{derived{}};
|
const meta::uvalue v{derived{}};
|
||||||
CHECK(can_get_as<derived>(v));
|
CHECK(v.can_get_as<derived>());
|
||||||
// CHECK_FALSE(can_get_as<derived&>(v));
|
CHECK_FALSE(v.can_get_as<derived2>());
|
||||||
// CHECK_FALSE(can_get_as<derived&&>(v));
|
|
||||||
CHECK(can_get_as<const derived&>(v));
|
|
||||||
// CHECK_FALSE(can_get_as<const derived&&>(v));
|
|
||||||
|
|
||||||
CHECK_FALSE(can_get_as<derived2>(v));
|
|
||||||
CHECK_FALSE(can_get_as<const derived2&>(v));
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const meta::uvalue v{derived{}};
|
const meta::uvalue v{derived{}};
|
||||||
CHECK(can_get_as<derived>(std::move(v)));
|
CHECK(std::move(v).can_get_as<derived>());
|
||||||
// CHECK_FALSE(can_get_as<derived&>(std::move(v)));
|
CHECK_FALSE(std::move(v).can_get_as<derived2>());
|
||||||
// CHECK_FALSE(can_get_as<derived&&>(std::move(v)));
|
|
||||||
CHECK(can_get_as<const derived&>(std::move(v)));
|
|
||||||
CHECK(can_get_as<const derived&&>(std::move(v)));
|
|
||||||
|
|
||||||
CHECK_FALSE(can_get_as<derived2>(std::move(v)));
|
|
||||||
CHECK_FALSE(can_get_as<const derived2&>(std::move(v)));
|
|
||||||
CHECK_FALSE(can_get_as<const derived2&&>(std::move(v)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,17 +105,17 @@ TEST_CASE("meta/meta_utilities/value") {
|
|||||||
|
|
||||||
SUBCASE("cast types") {
|
SUBCASE("cast types") {
|
||||||
static_assert(std::is_same_v<
|
static_assert(std::is_same_v<
|
||||||
decltype(std::declval<meta::uvalue&>().get_as_ref<ivec2>()),
|
decltype(std::declval<meta::uvalue&>().get_as<ivec2>()),
|
||||||
ivec2&>);
|
ivec2&>);
|
||||||
static_assert(std::is_same_v<
|
static_assert(std::is_same_v<
|
||||||
decltype(std::declval<meta::uvalue&&>().get_as_ref<ivec2>()),
|
decltype(std::declval<meta::uvalue&&>().get_as<ivec2>()),
|
||||||
ivec2&&>);
|
ivec2&>);
|
||||||
static_assert(std::is_same_v<
|
static_assert(std::is_same_v<
|
||||||
decltype(std::declval<const meta::uvalue&>().get_as_ref<ivec2>()),
|
decltype(std::declval<const meta::uvalue&>().get_as<ivec2>()),
|
||||||
const ivec2&>);
|
const ivec2&>);
|
||||||
static_assert(std::is_same_v<
|
static_assert(std::is_same_v<
|
||||||
decltype(std::declval<const meta::uvalue&&>().get_as_ref<ivec2>()),
|
decltype(std::declval<const meta::uvalue&&>().get_as<ivec2>()),
|
||||||
const ivec2&&>);
|
const ivec2&>);
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBCASE("ivec2{}") {
|
SUBCASE("ivec2{}") {
|
||||||
@@ -133,13 +133,13 @@ TEST_CASE("meta/meta_utilities/value") {
|
|||||||
CHECK_FALSE(*val);
|
CHECK_FALSE(*val);
|
||||||
CHECK_FALSE(val[0]);
|
CHECK_FALSE(val[0]);
|
||||||
|
|
||||||
CHECK_FALSE(val.can_get_as_ref<ivec2>());
|
CHECK_FALSE(val.can_get_as<ivec2>());
|
||||||
CHECK_FALSE(std::as_const(val).can_get_as_ref<ivec2>());
|
CHECK_FALSE(std::as_const(val).can_get_as<ivec2>());
|
||||||
|
|
||||||
CHECK_THROWS(std::ignore = val.get_as_ref<int>());
|
CHECK_THROWS(std::ignore = val.get_as<int>());
|
||||||
CHECK_THROWS(std::ignore = std::as_const(val).get_as_ref<int>());
|
CHECK_THROWS(std::ignore = std::as_const(val).get_as<int>());
|
||||||
CHECK_THROWS(std::ignore = std::move(val).get_as_ref<int>());
|
CHECK_THROWS(std::ignore = std::move(val).get_as<int>());
|
||||||
CHECK_THROWS(std::ignore = std::move(std::as_const(val)).get_as_ref<int>());
|
CHECK_THROWS(std::ignore = std::move(std::as_const(val)).get_as<int>());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -195,20 +195,20 @@ TEST_CASE("meta/meta_utilities/value") {
|
|||||||
CHECK(val == ivec2{1,2});
|
CHECK(val == ivec2{1,2});
|
||||||
CHECK(val == meta::uvalue{ivec2{1,2}});
|
CHECK(val == meta::uvalue{ivec2{1,2}});
|
||||||
|
|
||||||
CHECK(val.get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(val.get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK(std::as_const(val).get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(std::as_const(val).get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK(std::move(val).get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(std::move(val).get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK(std::move(std::as_const(val)).get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(std::move(std::as_const(val)).get_as<ivec2>() == ivec2{1,2});
|
||||||
|
|
||||||
CHECK_THROWS(std::ignore = val.get_as_ref<ivec3>());
|
CHECK_THROWS(std::ignore = val.get_as<ivec3>());
|
||||||
CHECK_THROWS(std::ignore = std::as_const(val).get_as_ref<ivec3>());
|
CHECK_THROWS(std::ignore = std::as_const(val).get_as<ivec3>());
|
||||||
CHECK_THROWS(std::ignore = std::move(val).get_as_ref<ivec3>());
|
CHECK_THROWS(std::ignore = std::move(val).get_as<ivec3>());
|
||||||
CHECK_THROWS(std::ignore = std::move(std::as_const(val)).get_as_ref<ivec3>());
|
CHECK_THROWS(std::ignore = std::move(std::as_const(val)).get_as<ivec3>());
|
||||||
|
|
||||||
CHECK(val.get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(val.get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK(std::as_const(val).get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(std::as_const(val).get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK_FALSE(val.can_get_as_ref<ivec3>());
|
CHECK_FALSE(val.can_get_as<ivec3>());
|
||||||
CHECK_FALSE(std::as_const(val).can_get_as_ref<ivec3>());
|
CHECK_FALSE(std::as_const(val).can_get_as<ivec3>());
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBCASE("const ivec2&") {
|
SUBCASE("const ivec2&") {
|
||||||
@@ -229,20 +229,20 @@ TEST_CASE("meta/meta_utilities/value") {
|
|||||||
CHECK(val == ivec2{1,2});
|
CHECK(val == ivec2{1,2});
|
||||||
CHECK(val == meta::uvalue{ivec2{1,2}});
|
CHECK(val == meta::uvalue{ivec2{1,2}});
|
||||||
|
|
||||||
CHECK(val.get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(val.get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK(std::as_const(val).get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(std::as_const(val).get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK(std::move(val).get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(std::move(val).get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK(std::move(std::as_const(val)).get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(std::move(std::as_const(val)).get_as<ivec2>() == ivec2{1,2});
|
||||||
|
|
||||||
CHECK_THROWS(std::ignore = val.get_as_ref<ivec3>());
|
CHECK_THROWS(std::ignore = val.get_as<ivec3>());
|
||||||
CHECK_THROWS(std::ignore = std::as_const(val).get_as_ref<ivec3>());
|
CHECK_THROWS(std::ignore = std::as_const(val).get_as<ivec3>());
|
||||||
CHECK_THROWS(std::ignore = std::move(val).get_as_ref<ivec3>());
|
CHECK_THROWS(std::ignore = std::move(val).get_as<ivec3>());
|
||||||
CHECK_THROWS(std::ignore = std::move(std::as_const(val)).get_as_ref<ivec3>());
|
CHECK_THROWS(std::ignore = std::move(std::as_const(val)).get_as<ivec3>());
|
||||||
|
|
||||||
CHECK(val.get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(val.get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK(std::as_const(val).get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(std::as_const(val).get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK_FALSE(val.can_get_as_ref<ivec3>());
|
CHECK_FALSE(val.can_get_as<ivec3>());
|
||||||
CHECK_FALSE(std::as_const(val).can_get_as_ref<ivec3>());
|
CHECK_FALSE(std::as_const(val).can_get_as<ivec3>());
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBCASE("ivec2&&") {
|
SUBCASE("ivec2&&") {
|
||||||
@@ -257,20 +257,20 @@ TEST_CASE("meta/meta_utilities/value") {
|
|||||||
CHECK(val == ivec2{1,2});
|
CHECK(val == ivec2{1,2});
|
||||||
CHECK(val == meta::uvalue{ivec2{1,2}});
|
CHECK(val == meta::uvalue{ivec2{1,2}});
|
||||||
|
|
||||||
CHECK(val.get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(val.get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK(std::as_const(val).get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(std::as_const(val).get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK(std::move(val).get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(std::move(val).get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK(std::move(std::as_const(val)).get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(std::move(std::as_const(val)).get_as<ivec2>() == ivec2{1,2});
|
||||||
|
|
||||||
CHECK_THROWS(std::ignore = val.get_as_ref<ivec3>());
|
CHECK_THROWS(std::ignore = val.get_as<ivec3>());
|
||||||
CHECK_THROWS(std::ignore = std::as_const(val).get_as_ref<ivec3>());
|
CHECK_THROWS(std::ignore = std::as_const(val).get_as<ivec3>());
|
||||||
CHECK_THROWS(std::ignore = std::move(val).get_as_ref<ivec3>());
|
CHECK_THROWS(std::ignore = std::move(val).get_as<ivec3>());
|
||||||
CHECK_THROWS(std::ignore = std::move(std::as_const(val)).get_as_ref<ivec3>());
|
CHECK_THROWS(std::ignore = std::move(std::as_const(val)).get_as<ivec3>());
|
||||||
|
|
||||||
CHECK(val.get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(val.get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK(std::as_const(val).get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(std::as_const(val).get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK_FALSE(val.can_get_as_ref<ivec3>());
|
CHECK_FALSE(val.can_get_as<ivec3>());
|
||||||
CHECK_FALSE(std::as_const(val).can_get_as_ref<ivec3>());
|
CHECK_FALSE(std::as_const(val).can_get_as<ivec3>());
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBCASE("const ivec2&&") {
|
SUBCASE("const ivec2&&") {
|
||||||
@@ -285,20 +285,20 @@ TEST_CASE("meta/meta_utilities/value") {
|
|||||||
CHECK(val == ivec2{1,2});
|
CHECK(val == ivec2{1,2});
|
||||||
CHECK(val == meta::uvalue{ivec2{1,2}});
|
CHECK(val == meta::uvalue{ivec2{1,2}});
|
||||||
|
|
||||||
CHECK(val.get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(val.get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK(std::as_const(val).get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(std::as_const(val).get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK(std::move(val).get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(std::move(val).get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK(std::move(std::as_const(val)).get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(std::move(std::as_const(val)).get_as<ivec2>() == ivec2{1,2});
|
||||||
|
|
||||||
CHECK_THROWS(std::ignore = val.get_as_ref<ivec3>());
|
CHECK_THROWS(std::ignore = val.get_as<ivec3>());
|
||||||
CHECK_THROWS(std::ignore = std::as_const(val).get_as_ref<ivec3>());
|
CHECK_THROWS(std::ignore = std::as_const(val).get_as<ivec3>());
|
||||||
CHECK_THROWS(std::ignore = std::move(val).get_as_ref<ivec3>());
|
CHECK_THROWS(std::ignore = std::move(val).get_as<ivec3>());
|
||||||
CHECK_THROWS(std::ignore = std::move(std::as_const(val)).get_as_ref<ivec3>());
|
CHECK_THROWS(std::ignore = std::move(std::as_const(val)).get_as<ivec3>());
|
||||||
|
|
||||||
CHECK(val.get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(val.get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK(std::as_const(val).get_as_ref<ivec2>() == ivec2{1,2});
|
CHECK(std::as_const(val).get_as<ivec2>() == ivec2{1,2});
|
||||||
CHECK_FALSE(val.can_get_as_ref<ivec3>());
|
CHECK_FALSE(val.can_get_as<ivec3>());
|
||||||
CHECK_FALSE(std::as_const(val).can_get_as_ref<ivec3>());
|
CHECK_FALSE(std::as_const(val).can_get_as<ivec3>());
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBCASE("value(value&&)") {
|
SUBCASE("value(value&&)") {
|
||||||
@@ -473,7 +473,7 @@ TEST_CASE("meta/meta_utilities/value") {
|
|||||||
const int* const pi = &i;
|
const int* const pi = &i;
|
||||||
const meta::uvalue v{*meta::uvalue{&pi}};
|
const meta::uvalue v{*meta::uvalue{&pi}};
|
||||||
CHECK(v.get_type() == meta::resolve_type<const int*>() );
|
CHECK(v.get_type() == meta::resolve_type<const int*>() );
|
||||||
CHECK(v.get_as_ref<const int*>() == pi);
|
CHECK(v.get_as<const int*>() == pi);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
int i{42};
|
int i{42};
|
||||||
@@ -572,23 +572,44 @@ TEST_CASE("meta/meta_utilities/value/functions") {
|
|||||||
namespace meta = meta_hpp;
|
namespace meta = meta_hpp;
|
||||||
|
|
||||||
SUBCASE("add") {
|
SUBCASE("add") {
|
||||||
|
{
|
||||||
|
meta::uvalue v{&ivec2::add};
|
||||||
|
CHECK(v.get_type() == meta::resolve_type<ivec2&(ivec2::*)(const ivec2&)>());
|
||||||
|
CHECK(v.get_as<decltype(&ivec2::add)>() == &ivec2::add);
|
||||||
|
CHECK((ivec2{1,2}.*(v.get_as<decltype(&ivec2::add)>()))(ivec2{3,4}) == ivec2(4,6));
|
||||||
|
}
|
||||||
{
|
{
|
||||||
const meta::uvalue v{&ivec2::add};
|
const meta::uvalue v{&ivec2::add};
|
||||||
CHECK(v.get_type() == meta::resolve_type<ivec2&(ivec2::*)(const ivec2&)>());
|
CHECK(v.get_type() == meta::resolve_type<ivec2&(ivec2::*)(const ivec2&)>());
|
||||||
CHECK((ivec2{1,2}.*(v.get_as_ref<decltype(&ivec2::add)>()))(ivec2{3,4}) == ivec2(4,6));
|
CHECK(v.get_as<decltype(&ivec2::add)>() == &ivec2::add);
|
||||||
|
CHECK((ivec2{1,2}.*(v.get_as<decltype(&ivec2::add)>()))(ivec2{3,4}) == ivec2(4,6));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBCASE("iadd2") {
|
SUBCASE("iadd2") {
|
||||||
|
{
|
||||||
|
meta::uvalue v{iadd2};
|
||||||
|
CHECK(v.get_type() == meta::resolve_type<ivec2(*)(ivec2, ivec2)>());
|
||||||
|
CHECK(v.get_as<decltype(&iadd2)>() == &iadd2);
|
||||||
|
CHECK((v.get_as<decltype(&iadd2)>())(ivec2{1,2}, ivec2{3,4}) == ivec2{4,6});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
meta::uvalue v{&iadd2};
|
||||||
|
CHECK(v.get_type() == meta::resolve_type<ivec2(*)(ivec2, ivec2)>());
|
||||||
|
CHECK(v.get_as<decltype(&iadd2)>() == &iadd2);
|
||||||
|
CHECK((v.get_as<decltype(&iadd2)>())(ivec2{1,2}, ivec2{3,4}) == ivec2{4,6});
|
||||||
|
}
|
||||||
{
|
{
|
||||||
const meta::uvalue v{iadd2};
|
const meta::uvalue v{iadd2};
|
||||||
CHECK(v.get_type() == meta::resolve_type<ivec2(*)(ivec2, ivec2)>());
|
CHECK(v.get_type() == meta::resolve_type<ivec2(*)(ivec2, ivec2)>());
|
||||||
CHECK((v.get_as_ref<decltype(&iadd2)>())(ivec2{1,2}, ivec2{3,4}) == ivec2{4,6});
|
CHECK(v.get_as<decltype(&iadd2)>() == &iadd2);
|
||||||
|
CHECK((v.get_as<decltype(&iadd2)>())(ivec2{1,2}, ivec2{3,4}) == ivec2{4,6});
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const meta::uvalue v{&iadd2};
|
const meta::uvalue v{&iadd2};
|
||||||
CHECK(v.get_type() == meta::resolve_type<ivec2(*)(ivec2, ivec2)>());
|
CHECK(v.get_type() == meta::resolve_type<ivec2(*)(ivec2, ivec2)>());
|
||||||
CHECK((v.get_as_ref<decltype(&iadd2)>())(ivec2{1,2}, ivec2{3,4}) == ivec2{4,6});
|
CHECK(v.get_as<decltype(&iadd2)>() == &iadd2);
|
||||||
|
CHECK((v.get_as<decltype(&iadd2)>())(ivec2{1,2}, ivec2{3,4}) == ivec2{4,6});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user