Skip to content

Commit

Permalink
added support for register base class property,
Browse files Browse the repository at this point in the history
while only register the derived class.

it used the same appraoch like for the member functions

closes #29
  • Loading branch information
acki-m committed Mar 31, 2017
1 parent 28dbc85 commit 5a90984
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 30 deletions.
12 changes: 12 additions & 0 deletions src/rttr/detail/misc/misc_type_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,18 @@ namespace detail
struct is_copy_constructible<std::unique_ptr<T>> : std::false_type {};

/////////////////////////////////////////////////////////////////////////////////////////

template<typename T>
struct property_traits;

template<typename A, typename C>
struct property_traits<A(C::*)>
{
using class_type = C;
};

/////////////////////////////////////////////////////////////////////////////////////////

} // end namespace detail
} // end namespace rttr

Expand Down
4 changes: 4 additions & 0 deletions src/rttr/detail/registration/bind_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ class registration::bind<detail::prop, Class_Type, A, acc_level> : public regist
bind(const std::shared_ptr<detail::registration_executer>& reg_exec, string_view name, A acc)
: registration_derived_t<Class_Type>(reg_exec), m_reg_exec(reg_exec), m_name(name), m_acc(acc)
{
detail::register_accessor_class_type_when_needed<Class_Type, A>();
m_reg_exec->add_registration_func(this);
}

Expand Down Expand Up @@ -481,6 +482,8 @@ class registration::bind<detail::prop, Class_Type, A1, A2, acc_level> : public r
bind(const std::shared_ptr<detail::registration_executer>& reg_exec, string_view name, A1 getter, A2 setter)
: registration_derived_t<Class_Type>(reg_exec), m_reg_exec(reg_exec), m_name(name), m_getter(getter), m_setter(setter)
{
detail::register_accessor_class_type_when_needed<Class_Type, A1>();
detail::register_accessor_class_type_when_needed<Class_Type, A2>();
m_reg_exec->add_registration_func(this);
}

Expand Down Expand Up @@ -569,6 +572,7 @@ class registration::bind<detail::prop_readonly, Class_Type, A, acc_level> : publ
bind(const std::shared_ptr<detail::registration_executer>& reg_exec, string_view name, A acc)
: registration_derived_t<Class_Type>(reg_exec), m_reg_exec(reg_exec), m_name(name), m_acc(acc)
{
detail::register_accessor_class_type_when_needed<Class_Type, A>();
m_reg_exec->add_registration_func(this);
}

Expand Down
78 changes: 48 additions & 30 deletions src/rttr/detail/registration/register_base_class_from_accessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

#include "rttr/detail/type/base_classes.h"
#include "rttr/detail/type/type_register.h"
#include "rttr/detail/misc/misc_type_traits.h"

#include <type_traits>

Expand All @@ -40,75 +41,92 @@ namespace rttr
namespace detail
{

template<typename ClassType, typename FuncClassType>
enable_if_t<contains<FuncClassType, typename ClassType::base_class_list>::value, void>
register_member_func_class_type_when_needed_3()
template<typename ClassType, typename AccClassType>
enable_if_t<contains<AccClassType, typename ClassType::base_class_list>::value, void>
register_member_accessor_class_type_when_needed_3()
{
}

template<typename ClassType, typename FuncClassType>
enable_if_t<!contains<FuncClassType, typename ClassType::base_class_list>::value, void>
register_member_func_class_type_when_needed_3()
template<typename ClassType, typename AccClassType>
enable_if_t<!contains<AccClassType, typename ClassType::base_class_list>::value, void>
register_member_accessor_class_type_when_needed_3()
{
base_class_info baseClassInfo = { type::get<FuncClassType>(), &rttr_cast_impl<ClassType, FuncClassType> };
base_class_info baseClassInfo = { type::get<AccClassType>(), &rttr_cast_impl<ClassType, AccClassType> };
type_register::register_base_class(type::get<ClassType>(), baseClassInfo);
}

template<typename ClassType, typename FuncClassType>
template<typename ClassType, typename AccClassType>
enable_if_t<has_base_class_list<ClassType>::value, void>
register_member_func_class_type_when_needed_2()
register_member_accessor_class_type_when_needed_2()
{
register_member_func_class_type_when_needed_3<ClassType, FuncClassType>();
register_member_accessor_class_type_when_needed_3<ClassType, AccClassType>();
}

template<typename ClassType, typename FuncClassType>
template<typename ClassType, typename AccClassType>
enable_if_t<!has_base_class_list<ClassType>::value, void>
register_member_func_class_type_when_needed_2()
register_member_accessor_class_type_when_needed_2()
{
base_class_info baseClassInfo = { type::get<FuncClassType>(), &rttr_cast_impl<ClassType, FuncClassType> };
base_class_info baseClassInfo = { type::get<AccClassType>(), &rttr_cast_impl<ClassType, AccClassType> };
type_register::register_base_class(type::get<ClassType>(), baseClassInfo);
}

template<typename ClassType, typename AccClassType>
enable_if_t<std::is_base_of<AccClassType, ClassType>::value, void>
register_member_accessor_class_type_when_needed_1()
{
register_member_accessor_class_type_when_needed_2<ClassType, AccClassType>();
}

template<typename ClassType, typename AccClassType>
enable_if_t<!std::is_base_of<AccClassType, ClassType>::value, void>
register_member_accessor_class_type_when_needed_1()
{
}

template<typename ClassType, typename FuncClassType>
enable_if_t<std::is_base_of<FuncClassType, ClassType>::value, void>
register_member_func_class_type_when_needed_1()
template<typename ClassType, typename AccClassType>
enable_if_t<!std::is_same<ClassType, AccClassType>::value, void>
register_member_accessor_class_type_when_needed()
{
register_member_func_class_type_when_needed_2<ClassType, FuncClassType>();
register_member_accessor_class_type_when_needed_1<ClassType, AccClassType>();
}

template<typename ClassType, typename FuncClassType>
enable_if_t<!std::is_base_of<FuncClassType, ClassType>::value, void>
register_member_func_class_type_when_needed_1()
template<typename ClassType, typename AccClassType>
enable_if_t<std::is_same<ClassType, AccClassType>::value, void>
register_member_accessor_class_type_when_needed()
{
}

template<typename ClassType, typename FuncClassType>
enable_if_t<!std::is_same<ClassType, FuncClassType>::value, void>
register_member_func_class_type_when_needed()
/////////////////////////////////////////////////////////////////////////////////////////

template<typename ClassType, typename F>
enable_if_t<std::is_member_function_pointer<F>::value && !std::is_member_object_pointer<F>::value, void>
register_accessor_class_type_when_needed()
{
register_member_func_class_type_when_needed_1<ClassType, FuncClassType>();
register_member_accessor_class_type_when_needed<ClassType, typename function_traits<F>::class_type>();
}

template<typename ClassType, typename FuncClassType>
enable_if_t<std::is_same<ClassType, FuncClassType>::value, void>
register_member_func_class_type_when_needed()
template<typename ClassType, typename F>
enable_if_t<!std::is_member_function_pointer<F>::value && std::is_member_object_pointer<F>::value, void>
register_accessor_class_type_when_needed()
{
register_member_accessor_class_type_when_needed<ClassType, typename property_traits<F>::class_type>();
}

template<typename ClassType, typename F>
enable_if_t<std::is_member_function_pointer<F>::value, void>
enable_if_t<std::is_member_function_pointer<F>::value && std::is_member_object_pointer<F>::value, void>
register_accessor_class_type_when_needed()
{
register_member_func_class_type_when_needed<ClassType, typename function_traits<F>::class_type>();
}

template<typename ClassType, typename F>
enable_if_t<!std::is_member_function_pointer<F>::value, void>
enable_if_t<!std::is_member_function_pointer<F>::value && !std::is_member_object_pointer<F>::value, void>
register_accessor_class_type_when_needed()
{
}

/////////////////////////////////////////////////////////////////////////////////////////


} // end namespace detail
} // end namespace rttr

Expand Down
37 changes: 37 additions & 0 deletions src/unit_tests/property/property_class_inheritance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,17 @@ struct bottom : left, right, right_2

}

struct base_prop_not_registered
{
base_prop_not_registered() : value(100) {}
int value;
};

struct derived_registered_prop : base_prop_not_registered
{

};

static double g_name;

/////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -145,6 +156,9 @@ RTTR_REGISTRATION
.property("bottom-static", &g_name) // double property
.property("bottom-static-protected", &g_name, registration::protected_access)
;

registration::class_<derived_registered_prop>("derived_registered_prop")
.property("value", &derived_registered_prop::value);
}

/////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -475,3 +489,26 @@ TEST_CASE("property - class - inheritance - invoke", "[property]")
}

/////////////////////////////////////////////////////////////////////////////////////////

TEST_CASE("property - base class not registered", "[property]")
{
type t_prop = type::get<derived_registered_prop>();
property prop = t_prop.get_property("value");
derived_registered_prop obj;

auto ret = prop.set_value(obj, 23);

CHECK(ret == true);
CHECK(obj.value == 23);

auto base_type = type::get<base_prop_not_registered>();

CHECK(t_prop.is_derived_from(base_type) == true);

auto range = base_type.get_derived_classes();

REQUIRE(range.size() == 1);
CHECK(*range.begin() == t_prop);
}

/////////////////////////////////////////////////////////////////////////////////////////

0 comments on commit 5a90984

Please sign in to comment.