@@ -109,6 +109,11 @@ namespace cpprtti | |||||
template<typename T_to> | template<typename T_to> | ||||
inline variant to() const; | inline variant to() const; | ||||
/** | |||||
* @brief Convert this variant to another type. | |||||
*/ | |||||
inline variant to(cpprtti::type_id id) const; | |||||
/** | /** | ||||
* @brief Convert this variant to another type. | * @brief Convert this variant to another type. | ||||
*/ | */ | ||||
@@ -129,6 +134,11 @@ namespace cpprtti | |||||
* @brief Check if the variant has a value assigned, if not throw an exception. | * @brief Check if the variant has a value assigned, if not throw an exception. | ||||
*/ | */ | ||||
inline void check_impl() const; | inline void check_impl() const; | ||||
/** | |||||
* @brief Check if the passed type id is supported by the type stored in this variant. | |||||
*/ | |||||
inline bool check_type(const cpprtti::type& t, type_id id) const; | |||||
}; | }; | ||||
constexpr decltype(auto) make_variant = cppmp::generic_predicate<__impl::variant_builder> { }; | constexpr decltype(auto) make_variant = cppmp::generic_predicate<__impl::variant_builder> { }; | ||||
@@ -8,6 +8,8 @@ | |||||
#include <cppmp/core/conditionals.h> | #include <cppmp/core/conditionals.h> | ||||
#include <cppmp/misc/generic_predicate.h> | #include <cppmp/misc/generic_predicate.h> | ||||
#include <cpprtti/types/class_type.h> | |||||
#include "variant.h" | #include "variant.h" | ||||
#include "exception.h" | #include "exception.h" | ||||
#include "../registry.h" | #include "../registry.h" | ||||
@@ -303,7 +305,7 @@ namespace cpprtti | |||||
{ | { | ||||
check_impl(); | check_impl(); | ||||
if (_impl->type.id() != get_type_id<cppmp::decay_t<T>>()) | |||||
if (!check_type(_impl->type, get_type_id<cppmp::decay_t<T>>())) | |||||
{ | { | ||||
throw exception( | throw exception( | ||||
error_code::variant_type_mismatch, | error_code::variant_type_mismatch, | ||||
@@ -326,7 +328,36 @@ namespace cpprtti | |||||
variant variant::to() const | variant variant::to() const | ||||
{ | { | ||||
using to_type = cppmp::decay_t<T_to>; | using to_type = cppmp::decay_t<T_to>; | ||||
return to(get_type_id<to_type>()); | |||||
auto * t = type().registry().find<to_type>(); | |||||
if (!t) | |||||
{ | |||||
throw exception( | |||||
error_code::variant_is_empty, | |||||
cppcore::string_builder() | |||||
<< "No known conversion from type '" | |||||
<< type().name() | |||||
<< "' to type '" | |||||
<< get_type_name<to_type>() | |||||
<< "'!"); | |||||
} | |||||
return to(*t); | |||||
} | |||||
variant variant::to(cpprtti::type_id id) const | |||||
{ | |||||
auto t = type().registry().find(id); | |||||
if (!t) | |||||
{ | |||||
throw exception( | |||||
error_code::variant_is_empty, | |||||
cppcore::string_builder() | |||||
<< "No known conversion from type '" | |||||
<< type().name() | |||||
<< "' to type id '" | |||||
<< id | |||||
<< "'!"); | |||||
} | |||||
return to(*t); | |||||
} | } | ||||
variant variant::to(const cpprtti::type& t) const | variant variant::to(const cpprtti::type& t) const | ||||
@@ -372,4 +403,25 @@ namespace cpprtti | |||||
} | } | ||||
} | } | ||||
bool variant::check_type(const cpprtti::type& t, type_id id) const | |||||
{ | |||||
if (t.id() == id) | |||||
return true; | |||||
if (t.rtti_type() == cpprtti::rtti_type::class_type) | |||||
{ | |||||
auto* _ct = dynamic_cast<const cpprtti::class_type*>(&t); | |||||
assert(_ct); | |||||
auto& ct = *_ct; | |||||
for (auto& kvp : ct.base_classes()) | |||||
{ | |||||
if (check_type(*kvp, id)) | |||||
return true; | |||||
} | |||||
} | |||||
return false; | |||||
} | |||||
} | } |
@@ -31,6 +31,11 @@ namespace cpprtti | |||||
type_id p_id, | type_id p_id, | ||||
const std::string& p_name); | const std::string& p_name); | ||||
/** | |||||
* @brief Get the vector of base classes. | |||||
*/ | |||||
inline const class_type_vector& base_classes() const; | |||||
/** | /** | ||||
* @brief Get a map of all registered members. | * @brief Get a map of all registered members. | ||||
*/ | */ | ||||
@@ -16,6 +16,9 @@ namespace cpprtti | |||||
: type(p_registry, p_id, p_name, rtti_type_t::class_type) | : type(p_registry, p_id, p_name, rtti_type_t::class_type) | ||||
{ } | { } | ||||
const class_type::class_type_vector& class_type::base_classes() const | |||||
{ return _base_classes; } | |||||
const member& class_type::member( | const member& class_type::member( | ||||
const std::string& p_name) const | const std::string& p_name) const | ||||
{ | { | ||||
@@ -54,12 +54,22 @@ namespace cpprtti | |||||
template<typename T_object> | template<typename T_object> | ||||
inline variant get(T_object& obj) const; | inline variant get(T_object& obj) const; | ||||
/** | |||||
* @brief Get the current value of the member. | |||||
*/ | |||||
inline variant get(const variant& obj) const; | |||||
/** | /** | ||||
* @brief Set the new value of the member. | * @brief Set the new value of the member. | ||||
*/ | */ | ||||
template<typename T_object, typename T_value> | template<typename T_object, typename T_value> | ||||
inline void set(T_object& obj, const T_value& value) const; | inline void set(T_object& obj, const T_value& value) const; | ||||
/** | |||||
* @brief Set the new value of the member. | |||||
*/ | |||||
inline void set(const variant& obj, const variant& value) const; | |||||
protected: | protected: | ||||
/** | /** | ||||
* @brief Get the current value of the member. | * @brief Get the current value of the member. | ||||
@@ -47,6 +47,9 @@ namespace cpprtti | |||||
return get_impl(make_variant(_owner.registry(), obj)); | return get_impl(make_variant(_owner.registry(), obj)); | ||||
} | } | ||||
variant member_variable::get(const variant& obj) const | |||||
{ return get_impl(obj); } | |||||
template<typename T_object, typename T_value> | template<typename T_object, typename T_value> | ||||
inline void member_variable::set(T_object& obj, const T_value& value) const | inline void member_variable::set(T_object& obj, const T_value& value) const | ||||
{ | { | ||||
@@ -64,6 +67,9 @@ namespace cpprtti | |||||
return set_impl(make_variant(_owner.registry(), obj), make_variant(_owner.registry(), value)); | return set_impl(make_variant(_owner.registry(), obj), make_variant(_owner.registry(), value)); | ||||
} | } | ||||
void member_variable::set(const variant& obj, const variant& value) const | |||||
{ return set_impl(obj, value); } | |||||
namespace __impl | namespace __impl | ||||
{ | { | ||||