#include <new>
#include <type_traits>
#include <utility>
template <typename F>
struct RAIIFunctor {
typedef typename std::remove_reference<F>::type functor_type;
typename std::aligned_storage<sizeof(functor_type),
std::alignment_of<functor_type>::value>::type store;
functor_type* f;
RAIIFunctor() : f{nullptr} {}
~RAIIFunctor() { destroy(); }
template <class T>
void assign(T&& t) {
destroy();
f = new(&store) functor_type {std::forward<T>(t)};
}
void destroy() {
if (f)
f->~functor_type();
f = nullptr;
}
void operator()() {
(*f)();
}
};
template <typename T>
void assign_lambda(T&& f)
{
static RAIIFunctor<T> func;
func.assign(std::forward<T>(f));
func();
}
#include <iostream>
#include <memory>
struct S {
int i_;
S(int i) : i_{i} {}
~S() { std::cout << "~S " << i_ << std::endl; }
};
int main() {
S s(1);
auto ptr = std::make_shared<S>(2);
assign_lambda([ptr](){ std::cout << "lambda\n";} );
std::cout << "end main\n";
}
I2luY2x1ZGUgPG5ldz4KI2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8dXRpbGl0eT4KCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgRj4KICAgIHN0cnVjdCBSQUlJRnVuY3RvciB7CiAgICAgIHR5cGVkZWYgdHlwZW5hbWUgc3RkOjpyZW1vdmVfcmVmZXJlbmNlPEY+Ojp0eXBlIGZ1bmN0b3JfdHlwZTsKCiAgICAgIHR5cGVuYW1lIHN0ZDo6YWxpZ25lZF9zdG9yYWdlPHNpemVvZihmdW5jdG9yX3R5cGUpLCAKICAgICAgICAgICAgICAgIHN0ZDo6YWxpZ25tZW50X29mPGZ1bmN0b3JfdHlwZT46OnZhbHVlPjo6dHlwZSBzdG9yZTsKICAgIAogICAgICBmdW5jdG9yX3R5cGUqIGY7CgogICAgICBSQUlJRnVuY3RvcigpIDogZntudWxscHRyfSB7fQogICAgICB+UkFJSUZ1bmN0b3IoKSB7IGRlc3Ryb3koKTsgfQoKICAgICAgdGVtcGxhdGUgPGNsYXNzIFQ+CiAgICAgIHZvaWQgYXNzaWduKFQmJiB0KSB7CiAgICAgICAgZGVzdHJveSgpOwogICAgICAgIGYgPSBuZXcoJnN0b3JlKSBmdW5jdG9yX3R5cGUge3N0ZDo6Zm9yd2FyZDxUPih0KX07CiAgICAgIH0KCiAgICAgIHZvaWQgZGVzdHJveSgpIHsKICAgICAgICBpZiAoZikgCiAgICAgICAgICBmLT5+ZnVuY3Rvcl90eXBlKCk7CiAgICAgICAgZiA9IG51bGxwdHI7CiAgICAgIH0KCiAgICAgIHZvaWQgb3BlcmF0b3IoKSgpIHsKICAgICAgICAoKmYpKCk7CiAgICAgIH0KICAgIH07CgoKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBUPgogICAgdm9pZCBhc3NpZ25fbGFtYmRhKFQmJiBmKQogICAgewogICAgICBzdGF0aWMgUkFJSUZ1bmN0b3I8VD4gZnVuYzsKCiAgICAgIGZ1bmMuYXNzaWduKHN0ZDo6Zm9yd2FyZDxUPihmKSk7CiAgICAgIGZ1bmMoKTsKICAgIH0KCiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPG1lbW9yeT4Kc3RydWN0IFMgewogIGludCBpXzsKICBTKGludCBpKSA6IGlfe2l9IHt9CiAgflMoKSB7IHN0ZDo6Y291dCA8PCAiflMgIiA8PCBpXyA8PCBzdGQ6OmVuZGw7IH0gIAp9OwoKaW50IG1haW4oKSB7CiAgUyBzKDEpOwogIGF1dG8gcHRyID0gc3RkOjptYWtlX3NoYXJlZDxTPigyKTsKICBhc3NpZ25fbGFtYmRhKFtwdHJdKCl7IHN0ZDo6Y291dCA8PCAibGFtYmRhXG4iO30gKTsKICBzdGQ6OmNvdXQgPDwgImVuZCBtYWluXG4iOwp9