How does the template parameter of std::function work? (implementation)

Viewed 27765

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!

5 Answers

To answer the question in the title. The parameter that std::function uses is a nice trick to pass many type parameters as a single template parameter. Those arguments being the argument types and the return type of a function.

It turns out 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:

Preferred syntax

boost::function<void(int*, int, int&, float&)> sum_avg;

Portable syntax

boost::function4<void, int*, int, int&, float&> sum_avg;

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.

Related