diff --git a/include/yorel/yomm2/core.hpp b/include/yorel/yomm2/core.hpp index 8426f659..146d9902 100644 --- a/include/yorel/yomm2/core.hpp +++ b/include/yorel/yomm2/core.hpp @@ -703,38 +703,8 @@ class method template struct thunk; - template< - auto Overrider, typename OverriderReturn, - typename... OverriderParameters> - struct thunk { - static auto fn(detail::remove_virtual... arg) -> Return; - using OverriderParameterTypeIds = detail::type_id_list< - Policy, - detail::spec_polymorphic_types< - Policy, DeclaredParameters, - detail::types>>; - }; - - template - struct override_; - friend class generator; - public: - template - struct override_fn; - - private: - template - struct override_ { - override_fn override_{nullptr}; - }; - - template - struct override_ { - override_fn add{&Container::next}; - }; - public: // Public aliases. using return_type = Return; @@ -753,9 +723,25 @@ class method template using next = detail::next_aux; + template + static Next next_fn; + + private: + template< + auto Overrider, typename OverriderReturn, + typename... OverriderParameters> + struct thunk { + static auto fn(detail::remove_virtual... arg) -> Return; + using OverriderParameterTypeIds = detail::type_id_list< + Policy, + detail::spec_polymorphic_types< + Policy, DeclaredParameters, + detail::types>>; + }; + template - struct override_fn { - explicit override_fn(Next* next = nullptr) { + struct override_fn_impl { + explicit override_fn_impl(Next* next = &next_fn) { static detail::definition_info info; if (info.method) { @@ -774,18 +760,59 @@ class method } }; - template - struct override - : override_::value> { - using type = override; // make it a meta-function + template + struct override_fn_aux; + + template + struct override_fn_aux : override_fn_impl{ + using override_fn_impl::override_fn_impl; }; - template - struct add_member_function - : override_fn::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(args)...); + } + + override_fn_impl impl{&next_fn}; + }; + + public: + template + struct override_fn : override_fn_aux { + using override_fn_aux::override_fn_aux; + }; template - struct add_member_functions : std::tuple...> {}; + struct override_fns { + std::tuple...> fns; + }; + + private: + template + struct override_aux; + + template + struct override_aux : override_fn { + override_aux() : override_fn(nullptr) { + } + }; + + template + struct override_aux : override_fn { + override_aux() : override_fn(&Container::next) { + } + }; + + public: + template + struct override + : override_aux::value> { + using type = override; // make it a meta-function + }; }; template< @@ -793,6 +820,12 @@ template< method method::fn; +template< + typename Name, typename Return, typename... Parameters, class... Options> +template +typename method::Next + method::next_fn; + template constexpr bool is_method = std::is_base_of_v; diff --git a/tests/test_blackbox.cpp b/tests/test_blackbox.cpp index b2b86bf5..4f6f2264 100644 --- a/tests/test_blackbox.cpp +++ b/tests/test_blackbox.cpp @@ -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)>; + +std::string kick_dog(Dog& dog) { + return "bark"; +} + +YOMM2_STATIC(kick::override_fn); + +std::string kick_bulldog(Bulldog& dog) { + return kick::next_fn(dog) + " and bite back"; +} + +YOMM2_STATIC(kick::override_fn); + +BOOST_AUTO_TEST_CASE(test_next_fn) { + update(); + + std::unique_ptr snoopy = std::make_unique(); + BOOST_TEST(kick::fn(*snoopy) == "bark"); + + std::unique_ptr hector = std::make_unique(); + BOOST_TEST(kick::fn(*hector) == "bark and bite back"); +} + +} // namespace test_next_fn + namespace errors { struct matrix { diff --git a/tests/test_member_method.cpp b/tests/test_member_method.cpp index 17c044f8..d895f58b 100644 --- a/tests/test_member_method.cpp +++ b/tests/test_member_method.cpp @@ -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>; };