#include <memory>
#include <functional>
//all done assuming interface is `void (*)()`
struct function_interface {
virtual void operator()()=0;
virtual std::unique_ptr<function_interface> copy()=0;
};
template<class T>
class function_impl : public function_interface {
T t;
public:
function_impl(T t_) : t(std::move(t_)) {};
void operator()() {t();}
virtual std::unique_ptr<function_interface> copy()
{return std::unique_ptr<function_interface>(new function_impl(t));}
};
class function {
std::unique_ptr<function_interface> ptr;
public:
template<class T>
function(T t) : ptr(new function_impl<T>(std::move(t))) {}
function(const function& rhs) : ptr(rhs.ptr->copy()) {}
function(function&& rhs) : ptr(std::move(rhs.ptr)) {}
void operator()() {(*ptr)();}
};
#include <iostream>
struct oid {
void operator()() {std::cout << "oid";}
};
void func() {std::cout << "function";}
int main() {
function a(func);
function b(a);
b();
function c((oid()));
c();
function d(c);
d();
}
I2luY2x1ZGUgPG1lbW9yeT4KI2luY2x1ZGUgPGZ1bmN0aW9uYWw+CgovL2FsbCBkb25lIGFzc3VtaW5nIGludGVyZmFjZSBpcyBgdm9pZCAoKikoKWAKCnN0cnVjdCBmdW5jdGlvbl9pbnRlcmZhY2UgewogICAgdmlydHVhbCB2b2lkIG9wZXJhdG9yKCkoKT0wOwogICAgdmlydHVhbCBzdGQ6OnVuaXF1ZV9wdHI8ZnVuY3Rpb25faW50ZXJmYWNlPiBjb3B5KCk9MDsKfTsKdGVtcGxhdGU8Y2xhc3MgVD4KY2xhc3MgZnVuY3Rpb25faW1wbCA6IHB1YmxpYyBmdW5jdGlvbl9pbnRlcmZhY2UgIHsKICAgIFQgdDsKcHVibGljOgogICAgZnVuY3Rpb25faW1wbChUIHRfKSA6IHQoc3RkOjptb3ZlKHRfKSkge307CiAgICB2b2lkIG9wZXJhdG9yKCkoKSB7dCgpO30KICAgIHZpcnR1YWwgc3RkOjp1bmlxdWVfcHRyPGZ1bmN0aW9uX2ludGVyZmFjZT4gY29weSgpCiAgICB7cmV0dXJuIHN0ZDo6dW5pcXVlX3B0cjxmdW5jdGlvbl9pbnRlcmZhY2U+KG5ldyBmdW5jdGlvbl9pbXBsKHQpKTt9Cn07CgpjbGFzcyBmdW5jdGlvbiB7CiAgICBzdGQ6OnVuaXF1ZV9wdHI8ZnVuY3Rpb25faW50ZXJmYWNlPiBwdHI7CnB1YmxpYzogCiAgICB0ZW1wbGF0ZTxjbGFzcyBUPgogICAgZnVuY3Rpb24oVCB0KSA6IHB0cihuZXcgZnVuY3Rpb25faW1wbDxUPihzdGQ6Om1vdmUodCkpKSB7fQogICAgZnVuY3Rpb24oY29uc3QgZnVuY3Rpb24mIHJocykgOiBwdHIocmhzLnB0ci0+Y29weSgpKSB7fQogICAgZnVuY3Rpb24oZnVuY3Rpb24mJiByaHMpIDogcHRyKHN0ZDo6bW92ZShyaHMucHRyKSkge30KICAgIHZvaWQgb3BlcmF0b3IoKSgpIHsoKnB0cikoKTt9Cn07CgojaW5jbHVkZSA8aW9zdHJlYW0+CnN0cnVjdCBvaWQgewogICAgdm9pZCBvcGVyYXRvcigpKCkge3N0ZDo6Y291dCA8PCAib2lkIjt9Cn07CnZvaWQgZnVuYygpIHtzdGQ6OmNvdXQgPDwgImZ1bmN0aW9uIjt9CgppbnQgbWFpbigpIHsKICAgIGZ1bmN0aW9uIGEoZnVuYyk7CiAgICBmdW5jdGlvbiBiKGEpOwogICAgYigpOyAgICAKICAgIGZ1bmN0aW9uIGMoKG9pZCgpKSk7CiAgICBjKCk7CiAgICBmdW5jdGlvbiBkKGMpOwogICAgZCgpOyAgICAKfQ==