Portál AbcLinuxu, 5. května 2025 18:41
class Request {}; class Response {}; class Controller { public: void BeforeAction(Request request, Response response) { std::cout << "BeforeAction" << std::endl; } template<typename C, typename void(C::* Action)(Request request, Response response)> void CallAction( Request request, Response response ) { this->BeforeAction(request, response); (static_cast<C*>(this)->*Action)(request, response); } }; class HomeController : public Controller { public: void HandleIndex( Request request, Response response ) { std::cout << "HandleIndex" << std::endl; } };
auto controller = HomeController(); auto request = Request(); auto response = Response(); controller.CallAction<HomeController, &HomeController::HandleIndex>(request, response);Ale chcel by som to ešte trošku "učesať" chcel by som aby som nemusel uvádzať ten prvý template parameter v CallAction action metóde (názov triedy). Teda buď aby som ho nemusel vôbec uvádzať, alebo aby sa odvodil nejako pomocou type inference. Viete mi prosím poradiť ako na to? Zdá sa mi zbytočne uvádzať ho 2x porušuje to princíp DRY.
Řešení dotazu:
proč prostě jakoby nepoužiješ polymorfizmuz?? :O :O stejně asi jako všecky ty voběkty musej mit to action by to fungovalo takže asi dědit z jednoho předka společnýho :O :O
keďže vopred neviem aký názov Akcií zvolím v potomkovi a akcie môžu mať praktiocky ľubovolný názov
jestli jako všecky berou jako argumenty 'request' a 'response' anic víc nic míň by nato šlo možná jít přez function pointery který by byly strkaný jako argument do tý metody 'CallAction' :O :O
jak se jako zbavit toho datovýho typu v šabloně navíc zatim nevim :D toje moc velikakakakánská c++ magie ukazatele na metody nastrkaný do šablony :D :D
class Request {}; class Response {}; class Controller { public: void BeforeAction(Request request, Response response) { std::cout << "BeforeAction" << std::endl; } template<typename C> void CallAction( void(C::*func)(Request, Response), Request request, Response response ) { this->BeforeAction(request, response); (static_cast<C*>(this)->*func)(request, response); } }; class HomeController : public Controller { public: void HandleIndex( Request request, Response response ) { std::cout << "HandleIndex" << std::endl; } }; int main() { auto controller = HomeController(); auto request = Request(); auto response = Response(); controller.CallAction(&HomeController::HandleIndex, request, response); }
nemaj se function pointery jakoby teďko dělat se std::function hele?? :O :O
std::function<void(Request, Response)>
, tak buď bude v místě volání jako parametr hnusný std::bind(&HomeController::HandleIndex, controller, std::placeholders::_1, std::placeholders::_2)
(který zároveň často likviduje optimalizace), nebo tam bude lambda [&](Request req, Response res){controller.HandleIndex(std::move(req), std::move(res));}
.
Member function pointer mi zde přijde jako asi přehlednější řešení podle požadavku autora dotazu. Codegen vypadá nejlepší s původním řešením autora ... https://godbolt.org/z/nYbGfoPrW (vlevo řešení s předáním member function jako parametru, uprostřed member function jako template parameter, vpravo předání přes std::function). Osobně jsem čekal, že codegen 1. a 2. bude stejný, že to kompilátor zoptimalizuje, ale asi se mu to moc nedaří ...
Toto sa mi dá skompilovať:
btw by se mi to zkompilovalo v g++ 10 sem musela přepsat jedenáctej řádek na
template<class C, void(C::* Action)(Request, Response)>
Tiskni
Sdílej:
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.