#include <memory>
#include <utility>
template <typename T>
struct function;
template <typename R, typename... A>
struct function<R(A...)> {
struct inner_fun_base {
virtual R call(A...) = 0; // this is where the type erasure happens
};
template <typename F>
struct inner_fun : inner_fun_base {
// here the type of the wrapped function object is not erased: it's F
inner_fun(F f) : f(f) {}
F f; // the lambda ends up here, by value
virtual R call(A... a) {
return f(std::forward<A>(a)...);
}
};
// no knowledge of what function object is here
std::unique_ptr<inner_fun_base> ptr;
template <typename F>
function(F f) // I'm going by value here for simplicity
:ptr(new inner_fun<F>(f)) {}
R operator()(A... a) {
// virtual call figures out at runtime the type we erased at compile-time
return ptr->call(std::forward<A>(a)...);
}
};
#include <iostream>
int main() {
function<bool(int)> f([](int n) { return n > 3; });
std::cout << f(2) << f(4);
}
I2luY2x1ZGUgPG1lbW9yeT4KI2luY2x1ZGUgPHV0aWxpdHk+Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IGZ1bmN0aW9uOwoKdGVtcGxhdGUgPHR5cGVuYW1lIFIsIHR5cGVuYW1lLi4uIEE+CnN0cnVjdCBmdW5jdGlvbjxSKEEuLi4pPiB7CiAgICBzdHJ1Y3QgaW5uZXJfZnVuX2Jhc2UgewogICAgICAgIHZpcnR1YWwgUiBjYWxsKEEuLi4pID0gMDsgLy8gdGhpcyBpcyB3aGVyZSB0aGUgdHlwZSBlcmFzdXJlIGhhcHBlbnMKICAgIH07CgogICAgdGVtcGxhdGUgPHR5cGVuYW1lIEY+CiAgICBzdHJ1Y3QgaW5uZXJfZnVuIDogaW5uZXJfZnVuX2Jhc2UgewogICAgLy8gaGVyZSB0aGUgdHlwZSBvZiB0aGUgd3JhcHBlZCBmdW5jdGlvbiBvYmplY3QgaXMgbm90IGVyYXNlZDogaXQncyBGCiAgICAgICAgaW5uZXJfZnVuKEYgZikgOiBmKGYpIHt9CiAgICAgICAgRiBmOyAvLyB0aGUgbGFtYmRhIGVuZHMgdXAgaGVyZSwgYnkgdmFsdWUKICAgICAgICB2aXJ0dWFsIFIgY2FsbChBLi4uIGEpIHsKICAgICAgICAgICAgcmV0dXJuIGYoc3RkOjpmb3J3YXJkPEE+KGEpLi4uKTsKICAgICAgICB9CiAgICB9OwoKICAgIC8vIG5vIGtub3dsZWRnZSBvZiB3aGF0IGZ1bmN0aW9uIG9iamVjdCBpcyBoZXJlCiAgICBzdGQ6OnVuaXF1ZV9wdHI8aW5uZXJfZnVuX2Jhc2U+IHB0cjsKCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgRj4KICAgIGZ1bmN0aW9uKEYgZikgLy8gSSdtIGdvaW5nIGJ5IHZhbHVlIGhlcmUgZm9yIHNpbXBsaWNpdHkKICAgIDpwdHIobmV3IGlubmVyX2Z1bjxGPihmKSkge30KCiAgICBSIG9wZXJhdG9yKCkoQS4uLiBhKSB7CiAgICAgICAgLy8gdmlydHVhbCBjYWxsIGZpZ3VyZXMgb3V0IGF0IHJ1bnRpbWUgdGhlIHR5cGUgd2UgZXJhc2VkIGF0IGNvbXBpbGUtdGltZQogICAgICAgIHJldHVybiBwdHItPmNhbGwoc3RkOjpmb3J3YXJkPEE+KGEpLi4uKTsKICAgIH0KfTsKCiNpbmNsdWRlIDxpb3N0cmVhbT4KCmludCBtYWluKCkgewogICAgZnVuY3Rpb248Ym9vbChpbnQpPiBmKFtdKGludCBuKSB7IHJldHVybiBuID4gMzsgfSk7CiAgICBzdGQ6OmNvdXQgPDwgZigyKSA8PCBmKDQpOwp9