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!
A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.
Defining a Function TemplateA function template starts with the keyword template followed by template parameter(s) inside <> which is followed by the function definition. In the above code, T is a template argument that accepts different data types ( int , float , etc.), and typename is a keyword.
Why we use :: template-template parameter? Explanation: It is used to adapt a policy into binary ones.
For example, given a specialization Stack<int>, “int” is a template argument. Instantiation: This is when the compiler generates a regular class, method, or function by substituting each of the template's parameters with a concrete type.
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
:
template<class T> class Function { }; // Parse the function type template<class Res, class Obj, class... ArgTypes> class Function<Res (Obj*, ArgTypes...)> { union Pointers { Res (*func)(Obj*, ArgTypes...); Res (Obj::*mem_func)(ArgTypes...); }; typedef Res Callback(Pointers&, Obj&, ArgTypes...); Pointers ptrs; Callback* callback; static Res call_func(Pointers& ptrs, Obj& obj, ArgTypes... args) { return (*ptrs.func)(&obj, args...); } static Res call_mem_func(Pointers& ptrs, Obj& obj, ArgTypes... args) { return (obj.*(ptrs.mem_func))(args...); } public: Function() : callback(0) { } // Parse the function type Function(Res (*func)(Obj*, ArgTypes...)) { ptrs.func = func; callback = &call_func; } // Parse the function type Function(Res (Obj::*mem_func)(ArgTypes...)) { ptrs.mem_func = mem_func; callback = &call_mem_func; } Function(const Function& function) { ptrs = function.ptrs; callback = function.callback; } Function& operator=(const Function& function) { ptrs = function.ptrs; callback = function.callback; return *this; } Res operator()(Obj& obj, ArgTypes... args) { if(callback == 0) throw 0; // throw an exception return (*callback)(ptrs, obj, args...); } };
Usage:
#include <iostream> struct Funny { void print(int i) { std::cout << "void (Funny::*)(int): " << i << std::endl; } }; void print(Funny* funny, int i) { std::cout << "void (*)(Funny*, int): " << i << std::endl; } int main(int argc, char** argv) { Funny funny; Function<void(Funny*, int)> wmw; wmw = &Funny::print; // void (Funny::*)(int) wmw(funny, 10); // void (Funny::*)(int) wmw = &print; // void (*)(Funny*, int) wmw(funny, 8); // void (*)(Funny*, int) return 0; }
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.
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).
struct X { int operator()(int x) { return doStuff(x+1);} int doStuff(int x) { return x+1;} }; X x; // You can now use x like a function int a = x(5);
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).
struct Y // Hold a member function pointer { int (X::*member)(int x); int operator(X* obj, int param) { return (obj->*member)(param);} }; X x; Y y; y.member = &X::doStuff; int a = y(&x,5);
Or even go further and bind parameters. So now all you need to provide is one of the parameters.
struct Z { int (X::*member)(int x); int param; Z(int (X::*m)(int), int p) : member(m), param(p) {} int operator()(X* obj) { return (obj->*member)(param);} int operator()(X& obj) { return (obj.*member)(param);} }; Z z(&X::doStuff,5); X x; int a = z(x);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With