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 7ebc3ca
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 43 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
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 7ebc3ca

Please sign in to comment.