uvalue upcasting support: wip

This commit is contained in:
BlackMATov
2022-11-02 01:21:54 +07:00
parent 48395d3b13
commit 014315699f
3 changed files with 136 additions and 8 deletions

View File

@@ -135,6 +135,11 @@ namespace meta_hpp::detail
return nullptr;
}
[[nodiscard]] inline const void* pointer_upcast(const void* ptr, const class_type& from, const class_type& to) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
return pointer_upcast(const_cast<void*>(ptr), from, to);
}
template < class_kind To, class_kind From >
[[nodiscard]] To* pointer_upcast(From* ptr) {
return static_cast<To*>(pointer_upcast(ptr, resolve_type<From>(), resolve_type<To>()));
@@ -142,7 +147,6 @@ namespace meta_hpp::detail
template < class_kind To, class_kind From >
[[nodiscard]] const To* pointer_upcast(const From* ptr) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
return pointer_upcast<To>(const_cast<From*>(ptr));
return static_cast<const To*>(pointer_upcast(ptr, resolve_type<From>(), resolve_type<To>()));
}
}

View File

@@ -17,6 +17,8 @@
#include "../meta_detail/value_traits/less_traits.hpp"
#include "../meta_detail/value_traits/ostream_traits.hpp"
#include "../meta_detail/value_utilities/utraits.hpp"
namespace meta_hpp
{
struct uvalue::vtable_t final {
@@ -327,53 +329,83 @@ namespace meta_hpp
template < typename T >
std::decay_t<T>& uvalue::cast() & {
using Tp = std::decay_t<T>;
if ( Tp* ptr = try_cast<Tp>() ) {
return *ptr;
}
detail::throw_exception_with("bad value cast");
}
template < typename T >
std::decay_t<T>&& uvalue::cast() && {
using Tp = std::decay_t<T>;
if ( Tp* ptr = try_cast<Tp>() ) {
return std::move(*ptr);
}
detail::throw_exception_with("bad value cast");
}
template < typename T >
const std::decay_t<T>& uvalue::cast() const & {
using Tp = std::decay_t<T>;
if ( const Tp* ptr = try_cast<const Tp>() ) {
return *ptr;
}
detail::throw_exception_with("bad value cast");
}
template < typename T >
const std::decay_t<T>&& uvalue::cast() const && {
using Tp = std::decay_t<T>;
if ( const Tp* ptr = try_cast<const Tp>() ) {
return std::move(*ptr);
}
detail::throw_exception_with("bad value cast");
}
template < typename T >
std::decay_t<T>* uvalue::try_cast() noexcept {
using Tp = std::decay_t<T>;
return get_type() == resolve_type<Tp>()
? vtable_t::storage_cast<Tp>(storage_)
: nullptr;
const any_type& from_type = get_type();
const any_type& to_type = resolve_type<Tp>();
if ( from_type == to_type ) {
return static_cast<Tp*>(data());
}
if ( from_type.is_class() && to_type.is_class() ) {
void* to_ptr = detail::pointer_upcast(data(), from_type.as_class(), to_type.as_class());
return static_cast<Tp*>(to_ptr);
}
return nullptr;
}
template < typename T >
const std::decay_t<T>* uvalue::try_cast() const noexcept {
using Tp = std::decay_t<T>;
return get_type() == resolve_type<Tp>()
? vtable_t::storage_cast<Tp>(storage_)
: nullptr;
const any_type& from_type = get_type();
const any_type& to_type = resolve_type<Tp>();
if ( from_type == to_type ) {
return static_cast<const Tp*>(data());
}
if ( from_type.is_class() && to_type.is_class() ) {
const void* to_ptr = detail::pointer_upcast(data(), from_type.as_class(), to_type.as_class());
return static_cast<const Tp*>(to_ptr);
}
return nullptr;
}
}