-1

[Edited] Based on the feedback from comments, I have rephrased my question.

In C++, is it possible to create a function func that receives another function f as a parameter, if the number of arguments of f might change?

According to this thread, a syntax in C like

void func ( void (*f)(int) );

would help if I already know the number of arguments f receives, but that's not my case.

I want to use func with different functions f1, f2, etc., each of them may or may not have the same number of parameters. For example, f1 could take only one argument, but f2 could take two. That's why I'm trying to look for a way to pass f without specifying the number of arguments. Thanks!

  • 2
    If you don't know the number of arguments `f` requires, then how do you plan to go about calling that function? Yes you can just pass a function as a `void *` and call it later, but if the function requires arguments you'll need to know what those arguments are if you intend to call it correctly. – h0r53 Sep 30 '21 at 18:57
  • 2
    Sure, `tempate void foo(Function func) { ... }`. Not sure how you would know how to cull `func` though. – NathanOliver Sep 30 '21 at 18:59
  • 1
    erasing type information is the simple part, the difficult part is to restore it when you need it. As Nathan said, when you call the function yuo need to know how many params to pass. Can you show how you would use `f` inside `func` ? – 463035818_is_not_an_ai Sep 30 '21 at 19:01
  • Thanks for the catch-up. I want to have the freedom of using `func` with different functions `f`, but I don't know if they would have the same number of parameters. – surrutiaquir Sep 30 '21 at 19:02
  • btw the Q&A you link is for C. In C++ the same question has radically different answers. – 463035818_is_not_an_ai Sep 30 '21 at 19:02
  • You could also consider `std::variant` or `std::any`. Possibly incorporate `std::function`. – Eljay Sep 30 '21 at 19:04
  • 3
    @h0r53: Actually `void *` is an object pointer and a function isn't an object. Storing a function pointer in an object pointer is non-portable. – Ben Voigt Sep 30 '21 at 19:05
  • C++ gives you all the tools you need to do anything you want with your code. This includes tools that, when misused, can result in utter gibberish code that compiles and runs and produces utter gibberish. – user4581301 Sep 30 '21 at 19:18
  • @BenVoigt I've always somewhat thought of them as the same but I do see the difference. I guess you have to technically cast a `void *` to a function pointer (which includes return type and argument type declarations). Thus, a `void *` is basically a generic pointer that could technically point to anything? Can you elaborate on the portability part? – h0r53 Sep 30 '21 at 19:29
  • 1
    @h0r53: Popular desktop OSes such as Windows and the *nix family provide the dynamic symbol lookup function, named `GetProcAddress` and `dlsym` respectively, which require this cast. Conversion between function pointer and object pointer really should never be used apart from the return values from the dynamic symbol lookup. Other platforms, like embedded code, may have totally different pointer size for code and data (this was even common on Intel x86 before the 32-bit flat memory model revolution) corresponding to the number of address bits for Flash memory and RAM respectively. – Ben Voigt Sep 30 '21 at 21:13
  • 1
    @h0r53: So for portability, don't use `void*` as an all-purpose pointer for functions, use some function-pointer type. `void(*)()` is a good candidate. The C and C++ standards guarantee you can roundtrip function addresses through other function pointer types, but if you try to store one in `void*` it might get truncated. – Ben Voigt Sep 30 '21 at 21:15
  • @h0r53 Sorry, I thought I pinged the OP there. – Code-Apprentice Oct 01 '21 at 15:07

1 Answers1

1

The Q&A you link is for C. In C++ you can pass a function pointer but not always this is the best alternative.

Your question leaves out the crucial part: How do you plan to call f in func when you don't know the number of parameters?

You can do type erasure and remove information of a type easily (eg number of arguments of a function), but latest when you call the function you need to know again how many parameters to pass.

As it isn't perfectly clear what you want to do with the fs that take different number of parameters I will interpret your question like this: Instead of passing functions of different arity to func you can pass a functor with overloaded operator(). Then you can call it with different number of parameters:

#include <iostream>
#include <string>

template <typename F>
void func(F f, int num_params){
    if (num_params == 1){
        f("Hello");
    } else if (num_params == 2) {
        f("Hello","World");
    }
}

struct functor {
    void operator()(const std::string& s){ std::cout << s << "\n";}
    void operator()(const std::string& s1,const std::string& s2) { std::cout << s1 << " " << s2 << "\n";}
};

int main() {
    func(functor{},1);
    func(functor{},2);
}

However, my func is only valid for a functor type that has both, an operator() that can be called with one string literal, and an operator() that can be called with two string literals.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185