| @@ -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 | ||||
| { | { | ||||