#include <iostream>
#include <functional>
#include <memory>
#include <tuple>
#include <typeinfo>

class B
{
public:

    B ()
      : m_v ( 0 )
    {
        std::cout << "ctor B @" << this << std::endl;
    }

    B (B const & other)
      : m_v ( other.m_v )
    {
        std::cout << "copy ctor B @" << this << std::endl;
    }

    ~B ()
    {
        std::cout << "dtor B @" << this << std::endl;
    }

    B & operator = (int v)
    {
        m_v = v;
        return *this;
    }

    operator int () const
    {
        return m_v;
    }

    B & operator ++ ()
    {
        ++m_v;
        return *this;
    }

private:

    int m_v;
};

auto f()
{
    B a;

    auto t0 = [=] () mutable
    {
        ++a;
        std::cout << "a = " << a << std::endl;
    };

    std::cout << typeid(t0).name () << std::endl;
    std::cout << "size of t0 = " << sizeof(t0) << std::endl;

    auto t1 = [=] () mutable
    {
        ++a;
        std::cout << "a = " << a << std::endl;
    };

    std::cout << "end of f" << std::endl;

    return std::make_tuple(t0, t1);
}

int main()
{
    uintptr_t esp;
    asm volatile ( "mov %%rsp, %0" : "=r" (esp) );
    std::cout << "esp = @" << (void *)esp << std::endl;

    auto tu0 = f();
    auto tu1 = f();

    asm volatile ( "mov %%rsp, %0" : "=r" (esp) );
    std::cout << "esp = @" << (void *)esp << std::endl;

    auto & t00 = std::get< 0 > ( tu0 );
    auto & t01 = std::get< 1 > ( tu0 );
    auto & t10 = std::get< 0 > ( tu1 );
    auto & t11 = std::get< 1 > ( tu1 );

    std::cout << "created first" << std::endl;

    std::cout << "call t00" << std::endl;
    t00();
    std::cout << "call t01" << std::endl;
    t01();
    std::cout << "call t10" << std::endl;
    t10();
    std::cout << "call t11" << std::endl;
    t11();

    std::cout << "end first" << std::endl;

    asm volatile ( "mov %%rsp, %0" : "=r" (esp) );
    std::cout << "esp = @" << (void *)esp << std::endl;

    return 0;
}
