#include <functional>
#include <utility>
#include <iostream>
#include <functional>
using namespace std;
// For generic types that are functors, delegate to its 'operator()'
template <typename T>
struct function_traits
: public function_traits<decltype(&T::operator())>
{};
// for pointers to member function
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const> {
enum { arity = sizeof...(Args) };
typedef function<ReturnType (Args...)> f_type;
};
// for pointers to member function
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) > {
enum { arity = sizeof...(Args) };
typedef function<ReturnType (Args...)> f_type;
};
// for function pointers
template <typename ReturnType, typename... Args>
struct function_traits<ReturnType (*)(Args...)> {
enum { arity = sizeof...(Args) };
typedef function<ReturnType (Args...)> f_type;
};
template <typename L>
static typename function_traits<L>::f_type make_function(L l){
return (typename function_traits<L>::f_type)(l);
}
//handles bind & multiple function call operator()'s
template<typename ReturnType, typename... Args, class T>
auto make_function(T&& t)
-> std::function<decltype(ReturnType(t(std::declval<Args>()...)))(Args...)>
{return {std::forward<T>(t)};}
//handles explicit overloads
template<typename ReturnType, typename... Args>
auto make_function(ReturnType(*p)(Args...))
-> std::function<ReturnType(Args...)> {
return {p};
}
//handles explicit overloads
template<typename ReturnType, typename... Args, typename ClassType>
auto make_function(ReturnType(ClassType::*p)(Args...))
-> std::function<ReturnType(Args...)> {
return {p};
}
// testing
using namespace std::placeholders;
int foo(int x, int y, int z) { return x + y + z;}
int foo1(int x, int y, int z) { return x + y + z;}
float foo1(int x, int y, float z) { return x + y + z;}
int main () {
//unambuiguous
auto f0 = make_function(foo);
auto f1 = make_function([](int x, int y, int z) { return x + y + z;});
cout << make_function([](int x, int y, int z) { return x + y + z;})(1,2,3) << endl;
int first = 4;
auto lambda_state = [=](int y, int z) { return first + y + z;}; //lambda with states
cout << make_function(lambda_state)(1,2) << endl;
//ambuiguous cases
auto f2 = make_function<int,int,int,int>(std::bind(foo,_1,_2,_3)); //bind results has multiple operator() overloads
cout << f2(1,2,3) << endl;
auto f3 = make_function<int,int,int,int>(foo1); //overload1
auto f4 = make_function<float,int,int,float>(foo1); //overload2
return 0;
}
I2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDx1dGlsaXR5PgojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDxmdW5jdGlvbmFsPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKLy8gRm9yIGdlbmVyaWMgdHlwZXMgdGhhdCBhcmUgZnVuY3RvcnMsIGRlbGVnYXRlIHRvIGl0cyAnb3BlcmF0b3IoKScKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnN0cnVjdCBmdW5jdGlvbl90cmFpdHMKICA6IHB1YmxpYyBmdW5jdGlvbl90cmFpdHM8ZGVjbHR5cGUoJlQ6Om9wZXJhdG9yKCkpPgp7fTsKCi8vIGZvciBwb2ludGVycyB0byBtZW1iZXIgZnVuY3Rpb24KdGVtcGxhdGUgPHR5cGVuYW1lIENsYXNzVHlwZSwgdHlwZW5hbWUgUmV0dXJuVHlwZSwgdHlwZW5hbWUuLi4gQXJncz4Kc3RydWN0IGZ1bmN0aW9uX3RyYWl0czxSZXR1cm5UeXBlKENsYXNzVHlwZTo6KikoQXJncy4uLikgY29uc3Q+IHsKICBlbnVtIHsgYXJpdHkgPSBzaXplb2YuLi4oQXJncykgfTsKICB0eXBlZGVmIGZ1bmN0aW9uPFJldHVyblR5cGUgKEFyZ3MuLi4pPiBmX3R5cGU7Cn07CgovLyBmb3IgcG9pbnRlcnMgdG8gbWVtYmVyIGZ1bmN0aW9uCnRlbXBsYXRlIDx0eXBlbmFtZSBDbGFzc1R5cGUsIHR5cGVuYW1lIFJldHVyblR5cGUsIHR5cGVuYW1lLi4uIEFyZ3M+CnN0cnVjdCBmdW5jdGlvbl90cmFpdHM8UmV0dXJuVHlwZShDbGFzc1R5cGU6OiopKEFyZ3MuLi4pID4gewogIGVudW0geyBhcml0eSA9IHNpemVvZi4uLihBcmdzKSB9OwogIHR5cGVkZWYgZnVuY3Rpb248UmV0dXJuVHlwZSAoQXJncy4uLik+IGZfdHlwZTsKfTsKCi8vIGZvciBmdW5jdGlvbiBwb2ludGVycwp0ZW1wbGF0ZSA8dHlwZW5hbWUgUmV0dXJuVHlwZSwgdHlwZW5hbWUuLi4gQXJncz4Kc3RydWN0IGZ1bmN0aW9uX3RyYWl0czxSZXR1cm5UeXBlICgqKShBcmdzLi4uKT4gIHsKICBlbnVtIHsgYXJpdHkgPSBzaXplb2YuLi4oQXJncykgfTsKICB0eXBlZGVmIGZ1bmN0aW9uPFJldHVyblR5cGUgKEFyZ3MuLi4pPiBmX3R5cGU7Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgTD4gCnN0YXRpYyB0eXBlbmFtZSBmdW5jdGlvbl90cmFpdHM8TD46OmZfdHlwZSBtYWtlX2Z1bmN0aW9uKEwgbCl7CiAgcmV0dXJuICh0eXBlbmFtZSBmdW5jdGlvbl90cmFpdHM8TD46OmZfdHlwZSkobCk7Cn0KCi8vaGFuZGxlcyBiaW5kICYgbXVsdGlwbGUgZnVuY3Rpb24gY2FsbCBvcGVyYXRvcigpJ3MKdGVtcGxhdGU8dHlwZW5hbWUgUmV0dXJuVHlwZSwgdHlwZW5hbWUuLi4gQXJncywgY2xhc3MgVD4KYXV0byBtYWtlX2Z1bmN0aW9uKFQmJiB0KSAKICAtPiBzdGQ6OmZ1bmN0aW9uPGRlY2x0eXBlKFJldHVyblR5cGUodChzdGQ6OmRlY2x2YWw8QXJncz4oKS4uLikpKShBcmdzLi4uKT4gCntyZXR1cm4ge3N0ZDo6Zm9yd2FyZDxUPih0KX07fQoKLy9oYW5kbGVzIGV4cGxpY2l0IG92ZXJsb2Fkcwp0ZW1wbGF0ZTx0eXBlbmFtZSBSZXR1cm5UeXBlLCB0eXBlbmFtZS4uLiBBcmdzPgphdXRvIG1ha2VfZnVuY3Rpb24oUmV0dXJuVHlwZSgqcCkoQXJncy4uLikpCiAgICAtPiBzdGQ6OmZ1bmN0aW9uPFJldHVyblR5cGUoQXJncy4uLik+IHsKICByZXR1cm4ge3B9Owp9CgovL2hhbmRsZXMgZXhwbGljaXQgb3ZlcmxvYWRzCnRlbXBsYXRlPHR5cGVuYW1lIFJldHVyblR5cGUsIHR5cGVuYW1lLi4uIEFyZ3MsIHR5cGVuYW1lIENsYXNzVHlwZT4KYXV0byBtYWtlX2Z1bmN0aW9uKFJldHVyblR5cGUoQ2xhc3NUeXBlOjoqcCkoQXJncy4uLikpIAogICAgLT4gc3RkOjpmdW5jdGlvbjxSZXR1cm5UeXBlKEFyZ3MuLi4pPiB7IAogIHJldHVybiB7cH07Cn0KCi8vIHRlc3RpbmcKdXNpbmcgbmFtZXNwYWNlIHN0ZDo6cGxhY2Vob2xkZXJzOwoKaW50IGZvbyhpbnQgeCwgaW50IHksIGludCB6KSB7IHJldHVybiB4ICsgeSArIHo7fQppbnQgZm9vMShpbnQgeCwgaW50IHksIGludCB6KSB7IHJldHVybiB4ICsgeSArIHo7fQpmbG9hdCBmb28xKGludCB4LCBpbnQgeSwgZmxvYXQgeikgeyByZXR1cm4geCArIHkgKyB6O30KCmludCBtYWluICgpIHsKICAvL3VuYW1idWlndW91cwogIGF1dG8gZjAgPSBtYWtlX2Z1bmN0aW9uKGZvbyk7CiAgYXV0byBmMSA9IG1ha2VfZnVuY3Rpb24oW10oaW50IHgsIGludCB5LCBpbnQgeikgeyByZXR1cm4geCArIHkgKyB6O30pOwogIGNvdXQgPDwgbWFrZV9mdW5jdGlvbihbXShpbnQgeCwgaW50IHksIGludCB6KSB7IHJldHVybiB4ICsgeSArIHo7fSkoMSwyLDMpIDw8IGVuZGw7CgogIGludCBmaXJzdCA9IDQ7CiAgYXV0byBsYW1iZGFfc3RhdGUgPSBbPV0oaW50IHksIGludCB6KSB7IHJldHVybiBmaXJzdCArIHkgKyB6O307IC8vbGFtYmRhIHdpdGggc3RhdGVzCiAgY291dCA8PCBtYWtlX2Z1bmN0aW9uKGxhbWJkYV9zdGF0ZSkoMSwyKSA8PCBlbmRsOwoKICAvL2FtYnVpZ3VvdXMgY2FzZXMKICBhdXRvIGYyID0gbWFrZV9mdW5jdGlvbjxpbnQsaW50LGludCxpbnQ+KHN0ZDo6YmluZChmb28sXzEsXzIsXzMpKTsgLy9iaW5kIHJlc3VsdHMgaGFzIG11bHRpcGxlIG9wZXJhdG9yKCkgb3ZlcmxvYWRzCiAgY291dCA8PCBmMigxLDIsMykgPDwgZW5kbDsKICBhdXRvIGYzID0gbWFrZV9mdW5jdGlvbjxpbnQsaW50LGludCxpbnQ+KGZvbzEpOyAgICAgLy9vdmVybG9hZDEKICBhdXRvIGY0ID0gbWFrZV9mdW5jdGlvbjxmbG9hdCxpbnQsaW50LGZsb2F0Pihmb28xKTsgLy9vdmVybG9hZDIKCiAgcmV0dXJuIDA7Cn0=