2

Say I have two overloaded function definitions:

int function_name(std::string);
int function_name(std::string, std::string);

I then use one of those functions as a parameter for a struct

struct My_struct
{
   std::function<int(std::string)> function_name;
}

...

My_struct function_struct = { function_name };

This gives an error because the compiler has no way of knowing which function I intend to give it.

As seen in this post, How do I specify a pointer to an overloaded function?, pointed out by @FantasticMrFox below, one solution is to use static_cast like so:

static_cast<int(*)(std::string)>(function_name);

However, an alternative is to use a lambda like so:

My_struct function_struct = { [](std::string my_string) { return function_name(my_string); };

This also informs the compiler which version I intend to use.

Is there a better way to do this? Or some syntax I'm missing that does this in an easier way?

Edit: After discussion in the comments, I edited this post to read more clearly as a comparison between function pointer and lambda.

cam.b
  • 127
  • 9
  • 1
    @KamilCuk i decided not to close as dup, i thought it was slightly different because of the conversion to std::function and why this needs the correct function pointer. I think we should re-open this unless there is a closer Duplicate. – Fantastic Mr Fox Mar 09 '23 at 23:13
  • @FantasticMrFox I don't think I see why you don't consider it as duplicate. Indeed, it's trying to create a `std::function` instead of passing function to algorithm, but the problem is strictly the same (down to taking a template as an argument). – Yksisarvinen Mar 09 '23 at 23:21
  • @Yksisarvinen Taking template as an argument? I am not sure what you mean. Also, this question and answer touches on lambdas v function pointers and can be used to compare them. I think it is different enough to have its own answer. – Fantastic Mr Fox Mar 09 '23 at 23:29
  • While writing I was naive to the linked post. But having read that, I will edit question to be more clearly asking about lambdas vs function pointer casts. – cam.b Mar 09 '23 at 23:41
  • You've made the minor mistake of taking by value then forgetting to move (should be `function_name(std::move(my_string))`). You can even make a handy macro that perfect forwards, which will usually do what you want: https://godbolt.org/z/78qn9hd91 – Artyer Mar 09 '23 at 23:42
  • @Artyer does this still apply to the lambda case? Where would `std::move` go in this case? – cam.b Mar 09 '23 at 23:48
  • @cam.b I'm talking about in the lambda, the parameter `std::string my_string` in the lambda is currently copied to initialize the argument of `function_name` when it could be moved from, so your lambda should be `[](std::string my_string) { return function_name(std::move(my_string)); }` – Artyer Mar 09 '23 at 23:52
  • @Artyer I know this was not included in my original question, but if that is an "out" parameter, I would need a copy, correct? If so I will include a note in OP to clarify. – cam.b Mar 09 '23 at 23:54

1 Answers1

4

It is slightly different to the case here: How do I specify a pointer to an overloaded function?

But it is quite similar, you want to get a std::function, but to achieve this you need to select the right function pointer. You will need to do this by informing the compiler which function to resolve with a static cast:

int function_name(std::string);
int function_name(std::string, std::string);

...

std::function<int(std::string)> f = static_cast<int(*)(std::string)>(function_name);

By defining the correct function pointer specifically you can create your std::function.

Here is a live example.

HOWEVER!

Write for readability first and you might be surprised by performance. For me personally seeing this:

My_struct function_struct = { [](std::string my_string) { return function_name(my_string); };

Is much clearer than this:

My_struct f = static_cast<int(*)(std::string)>(function_name);

Because you don't need function pointers. And when you look at the disassembly of each you may be surprised to find that the lambda version may actually generate less assembly code because the compiler can do more tricky things with it.

Fantastic Mr Fox
  • 32,495
  • 27
  • 95
  • 175