#include <iostream>
#include <functional>
#include <string>
namespace fx {
template<int I> struct placeholder{};
}
namespace std{
template<int I>
struct is_placeholder< ::fx::placeholder<I>> : std::integral_constant<int, I>{};
}
namespace fx {
template <size_t... Is>
struct indices {};
template <size_t N, std::size_t... Is>
struct build_indices : build_indices<N-1, N-1, Is...> {};
template <size_t... Is>
struct build_indices<0, Is...> : indices<Is...> {};
template<std::size_t... Is, class F, class... Args>
auto easy_bind(indices<Is...>, F const& f, Args&&... args)
-> decltype(std::bind(f, std::forward<Args>(args)..., placeholder<Is + 1>{}...))
{
return std::bind(f, std::forward<Args>(args)..., placeholder<Is + 1>{}...);
}
template<class R, class... FArgs, class... Args>
auto easy_bind(std::function<R(FArgs...)> f, Args&&... args)
-> decltype(fx::easy_bind(build_indices<sizeof...(FArgs) - sizeof...(Args)>{}, f, std::forward<Args>(args)...)) {
return fx::easy_bind(build_indices<sizeof...(FArgs) - sizeof...(Args)>{}, f, std::forward<Args>(args)...);
}
}
//Test Case:
struct SomeStruct {
public:
void function(int x, float y, std::string str) {
std::cout << x << " " << y << " " << str << std::endl;
}
};
using Functor = std::function<void(SomeStruct*,int,float,std::string)>;
int main() {
Functor functor = &SomeStruct::function;
auto func1 = fx::easy_bind(functor, new SomeStruct);
func1(5, 2.5, "Test1");
auto func2 = fx::easy_bind(Functor(&SomeStruct::function), new SomeStruct);
func2(5, 2.5, "Test2");
auto func3 = fx::easy_bind(&SomeStruct::function, new SomeStruct);
func3(5, 2.5, "Test3");
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8ZnVuY3Rpb25hbD4KI2luY2x1ZGUgPHN0cmluZz4KCm5hbWVzcGFjZSBmeCB7CiAgICB0ZW1wbGF0ZTxpbnQgST4gc3RydWN0IHBsYWNlaG9sZGVye307Cn0KCm5hbWVzcGFjZSBzdGR7CiAgICB0ZW1wbGF0ZTxpbnQgST4KICAgIHN0cnVjdCBpc19wbGFjZWhvbGRlcjwgOjpmeDo6cGxhY2Vob2xkZXI8ST4+IDogc3RkOjppbnRlZ3JhbF9jb25zdGFudDxpbnQsIEk+e307Cn0KCm5hbWVzcGFjZSBmeCB7CiAgICB0ZW1wbGF0ZSA8c2l6ZV90Li4uIElzPgogICAgc3RydWN0IGluZGljZXMge307CgogICAgdGVtcGxhdGUgPHNpemVfdCBOLCBzdGQ6OnNpemVfdC4uLiBJcz4KICAgIHN0cnVjdCBidWlsZF9pbmRpY2VzIDogYnVpbGRfaW5kaWNlczxOLTEsIE4tMSwgSXMuLi4+IHt9OwoKICAgIHRlbXBsYXRlIDxzaXplX3QuLi4gSXM+CiAgICBzdHJ1Y3QgYnVpbGRfaW5kaWNlczwwLCBJcy4uLj4gOiBpbmRpY2VzPElzLi4uPiB7fTsKCiAgICB0ZW1wbGF0ZTxzdGQ6OnNpemVfdC4uLiBJcywgY2xhc3MgRiwgY2xhc3MuLi4gQXJncz4KICAgIGF1dG8gZWFzeV9iaW5kKGluZGljZXM8SXMuLi4+LCBGIGNvbnN0JiBmLCBBcmdzJiYuLi4gYXJncykKICAgIC0+IGRlY2x0eXBlKHN0ZDo6YmluZChmLCBzdGQ6OmZvcndhcmQ8QXJncz4oYXJncykuLi4sIHBsYWNlaG9sZGVyPElzICsgMT57fS4uLikpCiAgICB7CiAgICAgICAgcmV0dXJuIHN0ZDo6YmluZChmLCBzdGQ6OmZvcndhcmQ8QXJncz4oYXJncykuLi4sIHBsYWNlaG9sZGVyPElzICsgMT57fS4uLik7CiAgICB9CgogICAgdGVtcGxhdGU8Y2xhc3MgUiwgY2xhc3MuLi4gRkFyZ3MsIGNsYXNzLi4uIEFyZ3M+CiAgICBhdXRvIGVhc3lfYmluZChzdGQ6OmZ1bmN0aW9uPFIoRkFyZ3MuLi4pPiBmLCBBcmdzJiYuLi4gYXJncykKICAgIC0+IGRlY2x0eXBlKGZ4OjplYXN5X2JpbmQoYnVpbGRfaW5kaWNlczxzaXplb2YuLi4oRkFyZ3MpIC0gc2l6ZW9mLi4uKEFyZ3MpPnt9LCBmLCBzdGQ6OmZvcndhcmQ8QXJncz4oYXJncykuLi4pKSB7CiAgICByZXR1cm4gZng6OmVhc3lfYmluZChidWlsZF9pbmRpY2VzPHNpemVvZi4uLihGQXJncykgLSBzaXplb2YuLi4oQXJncyk+e30sIGYsIHN0ZDo6Zm9yd2FyZDxBcmdzPihhcmdzKS4uLik7CiAgICB9Cn0KCi8vVGVzdCBDYXNlOgpzdHJ1Y3QgU29tZVN0cnVjdCB7CnB1YmxpYzoKICAgIHZvaWQgZnVuY3Rpb24oaW50IHgsIGZsb2F0IHksIHN0ZDo6c3RyaW5nIHN0cikgewogICAgICAgIHN0ZDo6Y291dCA8PCB4IDw8ICIgIiA8PCB5IDw8ICIgIiA8PCBzdHIgPDwgc3RkOjplbmRsOyAgICAKICAgIH0KfTsKCnVzaW5nIEZ1bmN0b3IgPSBzdGQ6OmZ1bmN0aW9uPHZvaWQoU29tZVN0cnVjdCosaW50LGZsb2F0LHN0ZDo6c3RyaW5nKT47CgppbnQgbWFpbigpIHsKCUZ1bmN0b3IgZnVuY3RvciA9ICZTb21lU3RydWN0OjpmdW5jdGlvbjsKICAgIGF1dG8gZnVuYzEgPSBmeDo6ZWFzeV9iaW5kKGZ1bmN0b3IsIG5ldyBTb21lU3RydWN0KTsKICAgIGZ1bmMxKDUsIDIuNSwgIlRlc3QxIik7CiAgICAKICAgIGF1dG8gZnVuYzIgPSBmeDo6ZWFzeV9iaW5kKEZ1bmN0b3IoJlNvbWVTdHJ1Y3Q6OmZ1bmN0aW9uKSwgbmV3IFNvbWVTdHJ1Y3QpOwogICAgZnVuYzIoNSwgMi41LCAiVGVzdDIiKTsKICAgIAogICAgYXV0byBmdW5jMyA9IGZ4OjplYXN5X2JpbmQoJlNvbWVTdHJ1Y3Q6OmZ1bmN0aW9uLCBuZXcgU29tZVN0cnVjdCk7CiAgICBmdW5jMyg1LCAyLjUsICJUZXN0MyIpOwogICAgCiAgICByZXR1cm4gMDsKfQ==
prog.cpp: In function ‘int main()’:
prog.cpp:56:69: error: no matching function for call to ‘easy_bind(void (SomeStruct::*)(int, float, std::string), SomeStruct*)’
auto func3 = fx::easy_bind(&SomeStruct::function, new SomeStruct);
^
prog.cpp:56:69: note: candidates are:
prog.cpp:25:10: note: template<unsigned int ...Is, class F, class ... Args> decltype (std::bind(f, (forward<Args>)(fx::easy_bind::args)..., {}...)) fx::easy_bind(fx::indices<Is ...>, const F&, Args&& ...)
auto easy_bind(indices<Is...>, F const& f, Args&&... args)
^
prog.cpp:25:10: note: template argument deduction/substitution failed:
prog.cpp:56:69: note: ‘void (SomeStruct::*)(int, float, std::string) {aka void (SomeStruct::*)(int, float, std::basic_string<char>)}’ is not derived from ‘fx::indices<Is ...>’
auto func3 = fx::easy_bind(&SomeStruct::function, new SomeStruct);
^
prog.cpp:32:10: note: template<class R, class ... FArgs, class ... Args> decltype (fx::easy_bind(fx::build_indices<(sizeof (FArgs ...) - sizeof (Args ...))>{}, f, (forward<Args>)(fx::easy_bind::args)...)) fx::easy_bind(std::function<_Res(_ArgTypes ...)>, Args&& ...)
auto easy_bind(std::function<R(FArgs...)> f, Args&&... args)
^
prog.cpp:32:10: note: template argument deduction/substitution failed:
prog.cpp:56:69: note: ‘void (SomeStruct::*)(int, float, std::string) {aka void (SomeStruct::*)(int, float, std::basic_string<char>)}’ is not derived from ‘std::function<_Res(_ArgTypes ...)>’
auto func3 = fx::easy_bind(&SomeStruct::function, new SomeStruct);
^