How does the argument list for std::function work - c++

I'm sorry if this is a very noobish question, but I'm confused on how you can specify std::function argument lists like this:
std::function<void(double)> func;
But in an actual function, this doesn't work:
void passFunc(void(double) func) {}
For the method above you have to specify a function pointer. So how is void(double) allowed to be passed into std::function? Is void(double) even a type? If not, how can it be in the argument list for std::function? If it is a type, why is it not valid to have void(double) be the type of a function parameter?

You can declare a type like that:
using Func = void(double);
But in the definition, you still need the name of the argument; otherwise, you could not use it in the function:
void passFunc(void func(double)) {}
Note that func is inbetween the return type and the arguments. If you don't like that, you can use the above-defined type:
void passFunc(Func func) {}

Related

Unable to pass function pointer as function param

I would like to pass function pointer as a function parameter.
Here is my code:
void AuthServerOpcodes::ValidateAndSetServerOpcode(ServerOpcode serverOpcode, void(*handlerFunc(std::vector<std::byte> data))) {}
Here is the function I would like to pass as second parameter in ValidateAndSetServerOpcode:
void AuthServerOpcodes::Test(std::vector<std::byte> data) {
std::cout << "all good" << std:end
}
Here is how I try to pass it:
ValidateAndSetServerOpcode(SMSG_LOGIN_REQUEST, &Test);
However this seems to be not the correct way. When I try to do it in that way I get error:
Cannot initialize a parameter of type 'void (*(*)
(std::vector<std::byte>))' with an rvalue of type 'void
(AuthServerOpcodes::*)(std::vector<std::byte>)': different return type
('void (*)' vs 'void')
Why is that and how can I fix it?
Pointers to member must be qualified with the class type, so you need to get the pointer you'll need to use
ValidateAndSetServerOpcode(SMSG_LOGIN_REQUEST, &AuthServerOpcodes::Test);
But it looks like you've tried that in the previous edit, so I guess you've called the function pointer to member incorrectly. You didn't show a minimal, reproducible example so I can't help you more, please create one. Anyway I've created a compiled example on Compiler Explorer
typedef void (AuthServerOpcodes::*HandlerFunc)(std::vector<std::byte> &);
void AuthServerOpcodes::ValidateAndSetServerOpcode(ServerOpcode serverOpcode,
HandlerFunc handlerFunc)
{
std::vector<std::byte> myVector;
(this->*handlerFunc)(myVector); // call the hander
}
void FreeStandingFunction(AuthServerOpcodes& opc,
AuthServerOpcodes::HandlerFunc handlerFunc,
std::vector<std::byte> &data)
{
(opc.*handlerFunc)(data);
}
As you can see the pointer to member must be called with ->* or .* and the whole dereferencing must be wrapped inside () because those operators has lower precedence than the function call operator ()
See also Function pointer to member function
Some off-topic note:
Don't use lines that are too long like that
Don't pass vectors by values unless you really need to preserve the outside value. Always pass by reference with const std::vector<>& (or remove const to modify the outside variable)
Use '\n' instead of std::endl
You can't do that.
There is no function pointer to that function, because it is a member function.
You can instead pass a pointer-to-member-function, or better yet a std::function bound to a lambda that captures the this pointer.
It's just a type mismatch, your function is a method of the AccountManager class,
so it has this signature similar to:
static void Login(AccountManager *this, std::vector<..> data);
You can either detach function from class, change your type definition of handlerFunc or consider different techniques like std::mem_fn or std:bind
https://en.cppreference.com/w/cpp/utility/functional/mem_fn
https://en.cppreference.com/w/cpp/utility/functional/bind

Apply template arguments to function without calling function?

How do I apply just the template arguments to a function that expects template arguments, without implicitly also calling the function with zero arguments? I want a function or delegate pointer instead of a value.
void foo(T)(double x) {}
auto bar() {
return foo!(int);
}
hack.d(36): Error: function hack.foo!int.foo(double x) is not callable using argument types ()
hack.d(36): missing argument for parameter #1: double x
If you had an ordinary function
void foo() {}
and you wanted a function pointer to it, how would you do that?
&foo
Now, suppose you have a template:
void foo(T)() {}
and want a pointer to a specific instance... you can probably guess at this point :)
&foo!arg

Casting function pointer to functor in C++

I have a function pointer type imported from another .hpp file. Something like:
typedef void (*PFN_func)(int i);
I want to create a functor of the same type:
std::function<PFN_func>
But this doesn't work.
I don't want a solution like
std::function<void(int)>
Because mt function pointer definition is much more complicated
You could do this:
std::function<std::remove_pointer<PFN_func>::type>
Removing the pointer from void (*)(int) gives the function type void(int).
For the case of a general callable, see Is it possible to figure out the parameter type and return type of a lambda?

Passing lambda functions to other methods

Do lambda function have a signature so that I can pass them around?
template<class Fn>
HRESULT foreach(Fn _fuction)
{
}
object->foreach(
[param1, param2] (int item)
{
}
);
object->foreach(
[param1, param2, param3] (int item)
{
}
);
I want to use a typedef function instead of templates, I think the type of the function will strict the formal parameters but will allow captured list to vary.
can I use typedef instead of templates to pass lambda functions around?
something like:
typedef void (*Fn)(int);
but allows lambda not function pointer.
I tried using std::fuction but seems not working.
The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed non-
union class type — called the closure type ...
(C++11 §5.1.2/3, emphasis mine)
My reading of this is that even if two lambda-expressions have the same parameter list, return type, and capture list, they nevertheless have different types.
auto f = []{};
typedef decltype(f) lambda_type;
void g(lambda_type lambda) { lambda(); }
int main() {
g(f); // OK
g([]{}); // error: type mismatch
}
So no, what you are trying to do cannot be done. As others have suggested, try using std::function, or retain the template (what's wrong with templates, anyway?)
The actual type of a lambda is unspecified. But they are convertible to function; in your case, std::function<void(int)> (void is the return type, the parameter types go in the parentheses).

Deduce function type of overloaded function based on argument types

Suppose there is an overloaded function:
void overloaded(int) {}
void overloaded(void) {}
Because I don't want to (or can) write down the full function signature (like void(int) or void(void)) I need to get this signature using only the function name (overloaded) and
its argument type(s) (int or void).
I tried several approaches using decltype and friends, but unfortunately to no success.
So, in short, I need something like this:
cout << typeid(
get_overload(overloaded,(int)0))::type /* where the magic happens */
.name() << endl;
If you're allowed to use the name overloaded inside the type function, this will do:
template<typename... A>
using sig = decltype(overloaded(std::declval<A>()...))(A...);
sig<int> gives void(int), and sig<> gives void().
This is just a wrapper of tclamb's solution in a template alias.