#include <type_traits>
#include <functional>
#include <iostream>
#include <cstdlib>
template <class Functor, class... Args>
void run_helper(std::false_type, Functor f, Args&&... args)
{
f(std::forward<Args>(args)...);
}
template <class Functor, class Arg0, class... Args>
void run_helper(std::true_type, Functor f, Arg0&& arg0, Args&&... args)
{
(std::forward<Arg0>(arg0).*f)(std::forward<Args>(args)...);
}
template <class Functor, class... Args>
void run(Functor f, Args&&... args)
{
run_helper(typename std::is_member_pointer<Functor>::type(),
f, std::forward<Args>(args)...);
}
void freeFunction(int n) { std::cout << n << "\n"; }
struct Foo
{
void memberFunction(int n) { std::cout << n << "\n"; }
};
struct Bar
{
void overloadedMemberFunction(int n) { std::cout << n << "\n"; }
void overloadedMemberFunction(long n) { std::abort(); }
};
struct Baz
{
template <class T>
void templateMemberFunction(T n) { std::cout << n << "\n"; }
};
int main() {
run(freeFunction, 1111);
auto lambda = [](int n){ std::cout << n << "\n"; };
run(lambda, 2222);
Foo foo;
run(&Foo::memberFunction, foo, 3333);
Bar bar;
run<void(Bar::*)(int)>(&Bar::overloadedMemberFunction, bar, 4444);
Baz baz;
run<void(Baz::*)(int)>(&Baz::templateMemberFunction, baz, 5555);
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8ZnVuY3Rpb25hbD4KI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8Y3N0ZGxpYj4KCnRlbXBsYXRlIDxjbGFzcyBGdW5jdG9yLCBjbGFzcy4uLiBBcmdzPgp2b2lkIHJ1bl9oZWxwZXIoc3RkOjpmYWxzZV90eXBlLCBGdW5jdG9yIGYsIEFyZ3MmJi4uLiBhcmdzKQp7CiAgICBmKHN0ZDo6Zm9yd2FyZDxBcmdzPihhcmdzKS4uLik7Cn0KCnRlbXBsYXRlIDxjbGFzcyBGdW5jdG9yLCBjbGFzcyBBcmcwLCBjbGFzcy4uLiBBcmdzPgp2b2lkIHJ1bl9oZWxwZXIoc3RkOjp0cnVlX3R5cGUsIEZ1bmN0b3IgZiwgQXJnMCYmIGFyZzAsIEFyZ3MmJi4uLiBhcmdzKQp7CiAgICAoc3RkOjpmb3J3YXJkPEFyZzA+KGFyZzApLipmKShzdGQ6OmZvcndhcmQ8QXJncz4oYXJncykuLi4pOwp9Cgp0ZW1wbGF0ZSA8Y2xhc3MgRnVuY3RvciwgY2xhc3MuLi4gQXJncz4Kdm9pZCBydW4oRnVuY3RvciBmLCBBcmdzJiYuLi4gYXJncykKewogICAgcnVuX2hlbHBlcih0eXBlbmFtZSBzdGQ6OmlzX21lbWJlcl9wb2ludGVyPEZ1bmN0b3I+Ojp0eXBlKCksCiAgICAgICAgICAgICAgIGYsIHN0ZDo6Zm9yd2FyZDxBcmdzPihhcmdzKS4uLik7Cn0KCnZvaWQgZnJlZUZ1bmN0aW9uKGludCBuKSB7IHN0ZDo6Y291dCA8PCBuIDw8ICJcbiI7IH0KCnN0cnVjdCBGb28KewoJdm9pZCBtZW1iZXJGdW5jdGlvbihpbnQgbikgeyBzdGQ6OmNvdXQgPDwgbiA8PCAiXG4iOyB9Cn07CgpzdHJ1Y3QgQmFyCnsKCXZvaWQgb3ZlcmxvYWRlZE1lbWJlckZ1bmN0aW9uKGludCBuKSB7IHN0ZDo6Y291dCA8PCBuIDw8ICJcbiI7IH0KCXZvaWQgb3ZlcmxvYWRlZE1lbWJlckZ1bmN0aW9uKGxvbmcgbikgeyBzdGQ6OmFib3J0KCk7IH0KfTsKCnN0cnVjdCBCYXoKewoJdGVtcGxhdGUgPGNsYXNzIFQ+Cgl2b2lkIHRlbXBsYXRlTWVtYmVyRnVuY3Rpb24oVCBuKSB7IHN0ZDo6Y291dCA8PCBuIDw8ICJcbiI7IH0KfTsKCmludCBtYWluKCkgewoJcnVuKGZyZWVGdW5jdGlvbiwgMTExMSk7CgkKCWF1dG8gbGFtYmRhID0gW10oaW50IG4peyBzdGQ6OmNvdXQgPDwgbiA8PCAiXG4iOyB9OwoJcnVuKGxhbWJkYSwgMjIyMik7CgkKCUZvbyBmb287CglydW4oJkZvbzo6bWVtYmVyRnVuY3Rpb24sIGZvbywgMzMzMyk7CgkKCUJhciBiYXI7CglydW48dm9pZChCYXI6OiopKGludCk+KCZCYXI6Om92ZXJsb2FkZWRNZW1iZXJGdW5jdGlvbiwgYmFyLCA0NDQ0KTsKCQoJQmF6IGJhejsKCXJ1bjx2b2lkKEJhejo6KikoaW50KT4oJkJhejo6dGVtcGxhdGVNZW1iZXJGdW5jdGlvbiwgYmF6LCA1NTU1KTsKfQ==