#include <functional>
#include <iostream>
 
class Foo final
{
public:
	Foo() { std::cout << "Default constructor" << std::endl; }
	Foo(const Foo&) { std::cout << "Copy constructor" << std::endl; }
	Foo(Foo&&) noexcept { std::cout << "Move constructor" << std::endl; }
 
	Foo& operator=(const Foo&)
	{
		std::cout << "Copy assignment" << std::endl;
 
		return *this;
	}
 
	Foo& operator=(Foo&&) noexcept
	{
		std::cout << "Move assignment" << std::endl;
 
		return *this;
	}
 
	std::function<void()> f() const noexcept
	{
		return [*this]{ g(); };
	}
 
	~Foo() noexcept
	{
		std::cout << "Destructor" << std::endl;
	}
 
private:
	void g() const noexcept
	{
		std::cout << "Hello, World! :-)" << std::endl;
	}
};
 
void f(std::function<void()> cb) noexcept
{
	if (cb)
	{
		cb();
	}
}
 
int main()
{
	std::function<void()> cb;
 
	std::cout << '1' << std::endl;
	{
		Foo foo;
		std::cout << '2' << std::endl;
		cb = foo.f();
		std::cout << '3' << std::endl;
	}
 
	std::cout << '4' << std::endl;
	f(std::move(cb));
	std::cout << '5' << std::endl;
 
	return 0;
}
				I2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDxpb3N0cmVhbT4KCmNsYXNzIEZvbyBmaW5hbAp7CnB1YmxpYzoKCUZvbygpIHsgc3RkOjpjb3V0IDw8ICJEZWZhdWx0IGNvbnN0cnVjdG9yIiA8PCBzdGQ6OmVuZGw7IH0KCUZvbyhjb25zdCBGb28mKSB7IHN0ZDo6Y291dCA8PCAiQ29weSBjb25zdHJ1Y3RvciIgPDwgc3RkOjplbmRsOyB9CglGb28oRm9vJiYpIG5vZXhjZXB0IHsgc3RkOjpjb3V0IDw8ICJNb3ZlIGNvbnN0cnVjdG9yIiA8PCBzdGQ6OmVuZGw7IH0KCQoJRm9vJiBvcGVyYXRvcj0oY29uc3QgRm9vJikKCXsKCQlzdGQ6OmNvdXQgPDwgIkNvcHkgYXNzaWdubWVudCIgPDwgc3RkOjplbmRsOwoKCQlyZXR1cm4gKnRoaXM7Cgl9CgkKCUZvbyYgb3BlcmF0b3I9KEZvbyYmKSBub2V4Y2VwdAoJewoJCXN0ZDo6Y291dCA8PCAiTW92ZSBhc3NpZ25tZW50IiA8PCBzdGQ6OmVuZGw7CgoJCXJldHVybiAqdGhpczsKCX0KCQoJc3RkOjpmdW5jdGlvbjx2b2lkKCk+IGYoKSBjb25zdCBub2V4Y2VwdAoJewoJCXJldHVybiBbKnRoaXNdeyBnKCk7IH07Cgl9CgkKCX5Gb28oKSBub2V4Y2VwdAoJewoJCXN0ZDo6Y291dCA8PCAiRGVzdHJ1Y3RvciIgPDwgc3RkOjplbmRsOwoJfQoKcHJpdmF0ZToKCXZvaWQgZygpIGNvbnN0IG5vZXhjZXB0Cgl7CgkJc3RkOjpjb3V0IDw8ICJIZWxsbywgV29ybGQhIDotKSIgPDwgc3RkOjplbmRsOwoJfQp9OwoKdm9pZCBmKHN0ZDo6ZnVuY3Rpb248dm9pZCgpPiBjYikgbm9leGNlcHQKewoJaWYgKGNiKQoJewoJCWNiKCk7Cgl9Cn0KCmludCBtYWluKCkKewoJc3RkOjpmdW5jdGlvbjx2b2lkKCk+IGNiOwoJCglzdGQ6OmNvdXQgPDwgJzEnIDw8IHN0ZDo6ZW5kbDsKCXsKCQlGb28gZm9vOwoJCXN0ZDo6Y291dCA8PCAnMicgPDwgc3RkOjplbmRsOwoJCWNiID0gZm9vLmYoKTsKCQlzdGQ6OmNvdXQgPDwgJzMnIDw8IHN0ZDo6ZW5kbDsKCX0KCglzdGQ6OmNvdXQgPDwgJzQnIDw8IHN0ZDo6ZW5kbDsKCWYoc3RkOjptb3ZlKGNiKSk7CglzdGQ6OmNvdXQgPDwgJzUnIDw8IHN0ZDo6ZW5kbDsKCglyZXR1cm4gMDsKfQ==