Skip to content

Commit

Permalink
rework overriders
Browse files Browse the repository at this point in the history
  • Loading branch information
jll63 committed Sep 15, 2024
1 parent 44003c2 commit dbae215
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 47 deletions.
113 changes: 73 additions & 40 deletions include/yorel/yomm2/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -703,38 +703,8 @@ class method<Name, Return(Parameters...), Options...>
template<auto, typename>
struct thunk;

template<
auto Overrider, typename OverriderReturn,
typename... OverriderParameters>
struct thunk<Overrider, OverriderReturn (*)(OverriderParameters...)> {
static auto fn(detail::remove_virtual<Parameters>... arg) -> Return;
using OverriderParameterTypeIds = detail::type_id_list<
Policy,
detail::spec_polymorphic_types<
Policy, DeclaredParameters,
detail::types<OverriderParameters...>>>;
};

template<class Container, bool has_next>
struct override_;

friend class generator;

public:
template<auto Function>
struct override_fn;

private:
template<class Container>
struct override_<Container, false> {
override_fn<Container::fn> override_{nullptr};
};

template<class Container>
struct override_<Container, true> {
override_fn<Container::fn> add{&Container::next};
};

public:
// Public aliases.
using return_type = Return;
Expand All @@ -753,9 +723,25 @@ class method<Name, Return(Parameters...), Options...>
template<class Container>
using next = detail::next_aux<method, Container>;

template<auto>
static Next next_fn;

private:
template<
auto Overrider, typename OverriderReturn,
typename... OverriderParameters>
struct thunk<Overrider, OverriderReturn (*)(OverriderParameters...)> {
static auto fn(detail::remove_virtual<Parameters>... arg) -> Return;
using OverriderParameterTypeIds = detail::type_id_list<
Policy,
detail::spec_polymorphic_types<
Policy, DeclaredParameters,
detail::types<OverriderParameters...>>>;
};

template<auto Function>
struct override_fn {
explicit override_fn(Next* next = nullptr) {
struct override_fn_impl {
explicit override_fn_impl(Next* next = &next_fn<Function>) {
static detail::definition_info info;

if (info.method) {
Expand All @@ -774,25 +760,72 @@ class method<Name, Return(Parameters...), Options...>
}
};

template<class Container>
struct override
: override_<Container, detail::has_next<Container>::value> {
using type = override; // make it a meta-function
template<auto Function, typename FunctionType>
struct override_fn_aux;

template<auto Function, typename FnReturnType, typename... FnParameters>
struct override_fn_aux<Function, FnReturnType (*)(FnParameters...)> : override_fn_impl<Function>{
using override_fn_impl<Function>::override_fn_impl;
};

template<auto F>
struct add_member_function
: override_fn<detail::member_function_thunk<F, decltype(F)>::fn> {};
template<
auto Function, class FnClass, typename FnReturnType,
typename... FnParameters>
struct override_fn_aux<
Function, FnReturnType (FnClass::*)(FnParameters...)> {
static auto fn(FnClass* this_, FnParameters&&... args) -> FnReturnType {
return (this_->*Function)(std::forward<FnParameters>(args)...);
}

override_fn_impl<fn> impl{&next_fn<Function>};
};

public:
template<auto Function>
struct override_fn : override_fn_aux<Function, decltype(Function)> {
using override_fn_aux<Function, decltype(Function)>::override_fn_aux;
};

template<auto... F>
struct add_member_functions : std::tuple<add_member_function<F>...> {};
struct override_fns {
std::tuple<override_fn<F>...> fns;
};

private:
template<class Container, bool HasNext>
struct override_aux;

template<class Container>
struct override_aux<Container, false> : override_fn<Container::fn> {
override_aux() : override_fn<Container::fn>(nullptr) {
}
};

template<class Container>
struct override_aux<Container, true> : override_fn<Container::fn> {
override_aux() : override_fn<Container::fn>(&Container::next) {
}
};

public:
template<class Container>
struct override
: override_aux<Container, detail::has_next<Container>::value> {
using type = override; // make it a meta-function
};
};

template<
typename Name, typename Return, typename... Parameters, class... Options>
method<Name, Return(Parameters...), Options...>
method<Name, Return(Parameters...), Options...>::fn;

template<
typename Name, typename Return, typename... Parameters, class... Options>
template<auto>
typename method<Name, Return(Parameters...), Options...>::Next
method<Name, Return(Parameters...), Options...>::next_fn;

template<typename T>
constexpr bool is_method = std::is_base_of_v<detail::method_info, T>;

Expand Down
10 changes: 6 additions & 4 deletions include/yorel/yomm2/macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,10 @@
YOMM2_SYMBOL(NAME), RETURN_TYPE ARGS, \
::yorel::yomm2::detail::types<__VA_ARGS__>>::type

#define YOMM2_DECLARE(...) yOMM2_DECLARE(yOMM2_WHEN_NOT_STATIC, __VA_ARGS__)
#define YOMM2_STATIC_DECLARE(...) yOMM2_DECLARE(yOMM2_WHEN_STATIC, __VA_ARGS__)
#define YOMM2_DECLARE(RETURN_TYPE, NAME, ARGS, ...) \
yOMM2_DECLARE(yOMM2_WHEN_NOT_STATIC, RETURN_TYPE, NAME, ARGS, __VA_ARGS__)
#define YOMM2_STATIC_DECLARE(RETURN_TYPE, NAME, ARGS, ...) \
yOMM2_DECLARE(yOMM2_WHEN_STATIC, RETURN_TYPE, NAME, ARGS, __VA_ARGS__)

#define yOMM2_DECLARE(IF_STATIC, RETURN_TYPE, NAME, ARGS, ...) \
struct YOMM2_SYMBOL(NAME); \
Expand Down Expand Up @@ -112,7 +114,7 @@
struct _yOMM2_spec { \
static NS::_yOMM2_method::return_type yOMM2_body ARGS; \
}; \
_yOMM2_method::override_fn<_yOMM2_spec::yOMM2_body> YOMM2_GENSYM(&next); \
_yOMM2_method::override_fn<_yOMM2_spec::yOMM2_body> YOMM2_GENSYM(&next); \
} \
} \
NS::_yOMM2_method::return_type NS::_yOMM2_spec::yOMM2_body ARGS
Expand Down Expand Up @@ -165,7 +167,7 @@
Inline NS::_yOMM2_method::next_type CONTAINER<RETURN_TYPE ARGS>::next; \
namespace { \
namespace NS { \
Inline _yOMM2_method::override_fn<CONTAINER<RETURN_TYPE ARGS>::fn> \
Inline _yOMM2_method::override_fn<CONTAINER<RETURN_TYPE ARGS>::fn> \
YOMM2_GENSYM(&CONTAINER<RETURN_TYPE ARGS>::next); \
} \
} \
Expand Down
39 changes: 39 additions & 0 deletions tests/test_blackbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,45 @@ BOOST_AUTO_TEST_CASE(simple) {

} // namespace matrices

namespace test_next_fn {

struct Animal {
virtual ~Animal() {
}
};

struct Dog : Animal {};
struct Bulldog : Dog {};

register_classes(Animal, Dog, Bulldog);

struct YOMM2_SYMBOL(kick);
using kick = method<YOMM2_SYMBOL(kick), std::string(virtual_<Animal&>)>;

std::string kick_dog(Dog& dog) {
return "bark";
}

YOMM2_STATIC(kick::override_fn<kick_dog>);

std::string kick_bulldog(Bulldog& dog) {
return kick::next_fn<kick_bulldog>(dog) + " and bite back";
}

YOMM2_STATIC(kick::override_fn<kick_bulldog>);

BOOST_AUTO_TEST_CASE(test_next_fn) {
update();

std::unique_ptr<Animal> snoopy = std::make_unique<Dog>();
BOOST_TEST(kick::fn(*snoopy) == "bark");

std::unique_ptr<Animal> hector = std::make_unique<Bulldog>();
BOOST_TEST(kick::fn(*hector) == "bark and bite back");
}

} // namespace test_next_fn

namespace errors {

struct matrix {
Expand Down
8 changes: 5 additions & 3 deletions tests/test_member_method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,14 @@ struct Payroll {
void pay_employee(const Employee&) {
balance -= 2000;
}
void pay_manager(const Manager&) {
balance -= 3000;
void pay_manager(const Manager& manager) {
auto pf = &pay_method::next_fn<&Payroll::pay_manager>;
pay_method::next_fn<&Payroll::pay_manager>(this, manager);
balance -= 1000;
}

public:
using pay_functions = Payroll::pay_method::add_member_functions<
using pay_functions = Payroll::pay_method::override_fns<
&Payroll::pay_employee, &Payroll::pay_manager>;
};

Expand Down

0 comments on commit dbae215

Please sign in to comment.