In Bjarne Stroustrup's home page (C++11 FAQ):
struct X { int foo(int); };
std::function<int(X*, int)> f;
f = &X::foo; //pointer to member
X x;
int v = f(&x, 5); //call X::foo() for x with 5
How does it work? How does std::function call a foo member function?
The template parameter is int(X*, int)
, is &X::foo
converted from the member function pointer to a non-member function pointer?!
(int(*)(X*, int))&X::foo //casting (int(X::*)(int) to (int(*)(X*, int))
To clarify: I know that we don't need to cast any pointer to use std::function, but I don't know how the internals of std::function handle this incompatibility between a member function pointer and a non-member function pointer. I don't know how the standard allows us to implement something like std::function!
How it does it (I believe) is left undefined (but I don't have a copy of the standard here).
But given all the different possibilities that need to be covered I have the feeling that deciphering the exact definition of how it works would be really hard: So I am not going to try.
But I think you would like to know how functors work and they are relatively simple. So here is a quick example.
Functors:
These are objects that act like functions.
They are very useful in template code as they often allow you to use objects or functions interchangeably. The great thing about functors though is that they can hold state (a sort of poor man's closure).
You can use the fact that functor hold state to hold things like parameters or the objects or the pointer to member methods (or any combination thereof).
Or even go further and bind parameters. So now all you need to provide is one of the parameters.
After getting help from other answers and comments, and reading GCC source code and C++11 standard, I found that it is possible to parse a function type (its return type and its argument types) by using partial template specialization and function overloading.
The following is a simple (and incomplete) example to implement something like
std::function
:Usage:
g++ seems to have an union which may keep either function pointer, member pointer or void pointer which probably points to a functor. Add overloads which appropriately flag which union member is valid and heavy casting to a soup and then it works...
To answer the question in the title. The parameter that
std::function
uses is a nice trick to pass many parameters as a single template parameter. Those arguments being the argument types and the return type of a function.It coincides that
std::function
tries to type-erase a general functor but that is just coincidence.As a matter of fact, once upon a time there were compilers that wouldn't accept such tricks and the
boost::function
precursor had a portable syntax by which all the parameters could be passed separately:https://www.boost.org/doc/libs/1_68_0/doc/html/function/tutorial.html#id-1.3.16.5.4
So that's how the template parameters of
std::function
work, at the end it is just a trick to make a lot of parameters look like a function call. Function pointers to that type of function are not necessarily involved in the class.They're not function pointers. That's what std::function exists for. It wraps whatever callable types you give it. You should check out boost::bind- it's often used to make member function pointers callable as (this, args).