If the function now looks like this:

std::function<void()> FAction; void SimpleButton::addAction(void(*Action)()) { FAction = Action; } 

and it works, then it is necessary that the addAction function take in itself an unknown number of arguments in advance and assign the functions to the FAction, i.e. what would work

 button.addAction(some_func, x, y , z, ...); 

Of course, it is probably possible to create such a std :: function that can copy any function.

  • Nothing is clear. What should addAction do with these unnecessary arguments ??? How should she "assign" them to the FAction ? - AnT 6:23 pm
  • Now I will try to explain: there is a Button class, for convenience, there is a std :: function <void ()>, which is executed when pressed. After creating a button on it, it should be possible to hang a previously prescribed function, BUT the number of parameters for this function can be different, so addAction should accept the function (link to it) and the Nth number of its parameters - Dictator _ zx

2 answers 2

You can wrap it in an anonymous functor:

  template < typename x_Action , typename... x_Args > void SimpleButton:: addAction ( x_Action & action , x_Args... args ) { FAction = decltype(FAction) { [=]() { action(args...); } }; } 
  • Those. What will the full function addButton look like and how can I "shove" an indefinite number of parameters? - Dictator _ zx
  • If anything, then there is a desire that would work and addAction (some_func, x); and addAction (other_func, x, y, z); - Dictator _ zx
  • Sorry, it does not work .. I completely copied addAction, wrote a simple little void button1_print (int x) {std :: cout << x << std :: endl; } and further to int mai (): SimpleButton button1 (the path to the button, 100, 100, 100, 300); button1.addAction (button1_print, 5); however, when trying to compile, vs produces an unresolved external character "" public: void __thiscall SimpleButton :: addAction <void __cdecl (int), int> (void (__cdecl &) (int), int) "(?? $ addAction @ $$ A6AXH @ ZH @ SimpleButton @@ QAEXA6AXH @ ZH @ Z) " - Dictator _ zx
  • Sorry I wrote crookedly - Dictator _ zx
  • @Dictator_zx Apparently there are several translation units in the project and you added the template code to one of the cpp files. Templates must be defined in header files. - VTT

In my opinion, it would be wiser to take std::function<void()> as an argument. The user of the interface will be able to capture the arguments on his own, for this purpose there are lambdas and std::bind in the language, allowing, among other things, capturing by reference.

 #include <utility> #include <functional> #include <iostream> class SimpleButton{ std::function<void()> _action; public: void setAction(std::function<void()> fn){ _action = std::move(fn); } void click(){ _action(); } }; void printAB(int a, int b){ std::cout<< a << ", " << b << '\n'; } void test(){ SimpleButton button; int a = 1; int b = 10; // a захватывается по значению, b - по ссылке button.setAction(std::bind(&printAB, a, std::ref(b))); button.click(); // 1, 10 a = 20; b = 200; button.click(); // 1, 200 // аналогично через лямбды button.setAction([a, &b]{ std::cout<< a << ", " << b << '\n'; }); button.click(); // 20, 200 a = 300; b = 3000; button.click(); // 20, 3000 }