Home > Software engineering >  How to declare the template argument for an overloaded function
How to declare the template argument for an overloaded function

Time:03-02

I have a fairly big project that, regarding this question, I can summarize with this structure:

void do_something()
{
    //...
}

template<typename F> void use_funct(F funct)
{
    // ...
    funct();
}

int main()
{
    // ...
    use_funct(do_something);
}

All is working ok until someone (me) decides to reformat a little minimizing some functions, rewriting as this minimum reproducible example:

void do_something(const int a, const int b)
{
    //...
}

void do_something()
{
    //...
    do_something(1,2);
}

template<typename F> void use_funct(F funct)
{
    // ...
    funct();
}

int main()
{
    // ...
    use_funct(do_something);
}

And now the code doesn't compile with error: no matching function for call where use_funct is instantiated.

Since the error message was not so clear to me and the changes were a lot I wasted a considerable amount of time to understand that the compiler couldn't deduce the template parameter because do_something could now refer to any of the overloaded functions.

I removed the ambiguity changing the function name, but I wonder if there's the possibility to avoid this error in the future not relying on template argument deduction. How could I specify in this case the template argument for do_something(), possibly without referring to a function pointer? I haven't the slightest idea to express explicitly:

use_funct<-the-one-with-no-arguments->(do_something);

CodePudding user response:

You can wrap the function in a lambda, or pass a function pointer after casting it to the type of the overload you want to call or explicitly specify the template parameter:

use_funct([](){ do_something (); });
use_funct(static_cast<void(*)()>(do_something));
use_funct<void()>(do_something);

Wrapping it in a lambda has the advantage, that it is possible to defer overload resolution to use_func. For example:

void do_something(int) {}

void do_something(double) {}

template<typename F> void use_funct(F funct) {   
    funct(1);    // calls do_something(int)
    funct(1.0);  // calls do_something(double)
}

int main() {   
    use_funct([](auto x){ do_something (x); });
}

[...] possibly without referring to a function pointer?

I am not sure what you mean or why you want to avoid that. void() is the type of the function, not a function pointer. If you care about spelling out the type, you can use an alias:

using func_type = void();
use_funct<func_type>(do_something);
  • Related