#include <iostream>
#include <memory>
#include <type_traits>
template <class F>
struct Decomposer;
template <class R, class A>
struct Decomposer<R (A)>
{
typedef R return_type;
typedef A argument_type;
};
template <class F>
struct my_function
{
typedef typename Decomposer<F>::return_type return_type;
typedef typename Decomposer<F>::argument_type argument_type;
return_type operator() (argument_type arg) const {
return (*impl)(arg);
}
template <class From>
my_function(From &&from)
{
struct ConcreteImpl : Impl
{
typename std::remove_reference<From>::type functor;
ConcreteImpl(From &&functor) : functor(std::forward<From>(functor)) {}
virtual return_type operator() (argument_type arg) const override
{
return functor(arg);
}
};
impl.reset(new ConcreteImpl(std::forward<From>(from)));
}
private:
struct Impl {
virtual ~Impl() {}
virtual return_type operator() (argument_type arg) const = 0;
};
std::unique_ptr<Impl> impl;
};
int main(int argc, char* argv[])
{
int mybool = 5;
auto foo = [&] (int arg) {
return mybool * arg;
};
my_function<int(int)> foo2 = foo;
int result = foo2(42);
std::cout << result << std::endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8bWVtb3J5PgojaW5jbHVkZSA8dHlwZV90cmFpdHM+Cgp0ZW1wbGF0ZSA8Y2xhc3MgRj4Kc3RydWN0IERlY29tcG9zZXI7Cgp0ZW1wbGF0ZSA8Y2xhc3MgUiwgY2xhc3MgQT4Kc3RydWN0IERlY29tcG9zZXI8UiAoQSk+CnsKICB0eXBlZGVmIFIgcmV0dXJuX3R5cGU7CiAgdHlwZWRlZiBBIGFyZ3VtZW50X3R5cGU7Cn07CgoKdGVtcGxhdGUgPGNsYXNzIEY+CnN0cnVjdCBteV9mdW5jdGlvbgp7CiAgdHlwZWRlZiB0eXBlbmFtZSBEZWNvbXBvc2VyPEY+OjpyZXR1cm5fdHlwZSByZXR1cm5fdHlwZTsKICB0eXBlZGVmIHR5cGVuYW1lIERlY29tcG9zZXI8Rj46OmFyZ3VtZW50X3R5cGUgYXJndW1lbnRfdHlwZTsKICAKICByZXR1cm5fdHlwZSBvcGVyYXRvcigpIChhcmd1bWVudF90eXBlIGFyZykgY29uc3QgewogIAlyZXR1cm4gKCppbXBsKShhcmcpOwogIH0KICAKICB0ZW1wbGF0ZSA8Y2xhc3MgRnJvbT4KICBteV9mdW5jdGlvbihGcm9tICYmZnJvbSkKICB7CiAgCXN0cnVjdCBDb25jcmV0ZUltcGwgOiBJbXBsCiAgCXsKICAJCXR5cGVuYW1lIHN0ZDo6cmVtb3ZlX3JlZmVyZW5jZTxGcm9tPjo6dHlwZSBmdW5jdG9yOwogIAkJQ29uY3JldGVJbXBsKEZyb20gJiZmdW5jdG9yKSA6IGZ1bmN0b3Ioc3RkOjpmb3J3YXJkPEZyb20+KGZ1bmN0b3IpKSB7fQogIAkJdmlydHVhbCByZXR1cm5fdHlwZSBvcGVyYXRvcigpIChhcmd1bWVudF90eXBlIGFyZykgY29uc3Qgb3ZlcnJpZGUKICAJCXsKICAJCQlyZXR1cm4gZnVuY3RvcihhcmcpOwogIAkJfQogIAl9OwogIAlpbXBsLnJlc2V0KG5ldyBDb25jcmV0ZUltcGwoc3RkOjpmb3J3YXJkPEZyb20+KGZyb20pKSk7CiAgfQoKcHJpdmF0ZToKICBzdHJ1Y3QgSW1wbCB7CiAgCXZpcnR1YWwgfkltcGwoKSB7fQogIAl2aXJ0dWFsIHJldHVybl90eXBlIG9wZXJhdG9yKCkgKGFyZ3VtZW50X3R5cGUgYXJnKSBjb25zdCA9IDA7CiAgfTsKICAKICBzdGQ6OnVuaXF1ZV9wdHI8SW1wbD4gaW1wbDsKfTsKCgppbnQgbWFpbihpbnQgYXJnYywgY2hhciogYXJndltdKQp7CiAgICBpbnQgbXlib29sID0gNTsKCiAgICBhdXRvIGZvbyA9IFsmXSAoaW50IGFyZykgewogICAgICAgIHJldHVybiBteWJvb2wgKiBhcmc7CiAgICB9OwoKICAgIG15X2Z1bmN0aW9uPGludChpbnQpPiBmb28yID0gZm9vOwoKICAgIGludCByZXN1bHQgPSBmb28yKDQyKTsKICAgIAogICAgc3RkOjpjb3V0IDw8IHJlc3VsdCA8PCBzdGQ6OmVuZGw7CgogICAgcmV0dXJuIDA7Cn0=