uvalue simplifying and usage example

This commit is contained in:
BlackMATov
2022-11-06 08:29:25 +07:00
parent 558e7b1342
commit 178ab50a8b
11 changed files with 470 additions and 623 deletions

View File

@@ -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;
}

View File

@@ -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;
} }
template < typename T, detail::decay_value_kind V > const auto is_a = [](const any_type& base, const any_type& derived){
[[nodiscard]] bool can_get_as(V&& value) noexcept { return (base == derived)
using Tp = std::decay_t<T>; || (base.is_class() && derived.is_class() && base.as_class().is_base_of(derived.as_class()));
static_assert(std::is_constructible_v<T, detail::add_cvref_t<V&&, Tp>>); };
const any_type& from_type = value.get_type(); if ( is_a(to_type, from_type) ) {
const any_type& to_type = resolve_type<Tp>(); 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 >
bool uvalue::can_get_as() const noexcept {
static_assert(std::is_same_v<T, std::decay_t<T>>);
const any_type& from_type = get_type();
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) {

View 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 = &rect;
CHECK(val.get_as<shape*>()->get_area() == 15);
CHECK(val.get_type() == meta::resolve_type<rectangle*>());
}

View File

@@ -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;
} }
template < typename T, detail::decay_value_kind V > const auto is_a = [](const any_type& base, const any_type& derived){
[[nodiscard]] bool can_get_as(V&& value) noexcept { return (base == derived)
using Tp = std::decay_t<T>; || (base.is_class() && derived.is_class() && base.as_class().is_base_of(derived.as_class()));
static_assert(std::is_constructible_v<T, detail::add_cvref_t<V&&, Tp>>); };
const any_type& from_type = value.get_type(); if ( is_a(to_type, from_type) ) {
const any_type& to_type = resolve_type<Tp>(); 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 >
bool uvalue::can_get_as() const noexcept {
static_assert(std::is_same_v<T, std::decay_t<T>>);
const any_type& from_type = get_type();
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) {

View File

@@ -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>());
} }
} }

View File

@@ -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}));

View File

@@ -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);
} }
} }
} }

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)));
} }
} }
} }

View File

@@ -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});
} }
} }
} }