// File: /workspace/github_cpp_makefile_star2_O2/onlyuser[P]Sandbox/test_c/c++14/main.cpp
// Function: main
int main(int argc, char** argv)
{
    // NOTE: won't compile
    //std::cout << "\ntest0" << std::endl;
    //{
    //    f0(g()); // rvalue won't bind to "A&"
    //}

    std::cout << "\ntest1" << std::endl;
    {
        f(the_a); // lvalue reference prefers "A&"
        f(g());   // rvalue reference links to "const A&", but not "A&" (why write to a temporary? that's what rvalue ref is for!)
    }

    std::cout << "\ntest2" << std::endl;
    {
        f2(the_a); // lvalue reference prefers "A&"
        f2(g());   // rvalue reference prefers "A&&" over "const A&"
    }

    std::cout << "\ntest3" << std::endl;
    {
        f2_forward(the_a); // preserves rvalueness despite rvalue collapse rule (T& + T&& ==> T&)
        f2_forward(g());   // preserves rvalueness despite rvalue collapse rule (T& + T&& ==> T&)
    }

    std::cout << "\ntest4" << std::endl;
    {
        std::shared_ptr<::A> shared_a = std::make_shared<::A>("outer");

        std::cout << "ENTER SCOPE" << std::endl;
        {
            auto unique_a = std::make_unique<::A>("inner");
            shared_a = std::move(unique_a); // exchanges ownership with outer
        }
        std::cout << "LEAVE SCOPE" << std::endl;
    }

    std::cout << "\ntest5" << std::endl;
    {
        ::A a1("outer");

        std::cout << "ENTER SCOPE" << std::endl;
        {
            ::A a2("inner");
            std::swap(a1, a2); // swap works as you'd expect; exchanges ownership with outer
        }
        std::cout << "LEAVE SCOPE" << std::endl;
    }

    std::cout << "\ntest6" << std::endl;
    {
        A(A(A("hello world"))); // anonymous construction of object of type A; RVO is default behavior unless use gcc switch -fno-elide-constructors
    }

    std::cout << "\ntest7" << std::endl;
    {
        A(A(A(), 0), 0); // anonymous construction of object of type A; RVO not possible because "A(A(A()))" pattern is broken
    }

    std::cout << "\ntest8" << std::endl;
    {
        {
            A(A(A())); // center A is local variable declaration of function pointer type
            std::cout << typeid(A).name() << std::endl; // A (A (*)())
        }

        {
            typedef A(A(A())); // center A is function pointer type
            std::cout << typeid(A).name() << std::endl; // A (A (*)())
        }
    }

    std::cout << "\ntest9" << std::endl;
    {
        std::vector<::A> v;
        v.emplace_back("hello world"); // emplace is unrelated to rvalue reference
    }

    std::cout << "\ntest10" << std::endl;
    {
        std::shared_ptr<A> a = std::make_shared<A>("hello world"); // std::make_shared is unrelated to rvalue reference
    }

    return 0;
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x40, %rsp
movq 0x4c76(%rip), %rdi      # 0x5fd8
leaq 0x1ce8(%rip), %rsi      # 0x3051
callq 0x10c0
movq %rax, %rdi
callq 0x1070
callq 0x12ac
leaq 0x10(%rsp), %rdi
callq 0x133d
callq 0x12c9
leaq 0x10(%rsp), %rdi
callq 0x1776
movq 0x4c3d(%rip), %rdi      # 0x5fd8
leaq 0x1cb6(%rip), %rsi      # 0x3058
callq 0x10c0
movq %rax, %rdi
callq 0x1070
callq 0x12e6
leaq 0x10(%rsp), %rdi
callq 0x133d
callq 0x1320
leaq 0x10(%rsp), %rdi
callq 0x1776
movq 0x4c04(%rip), %rdi      # 0x5fd8
leaq 0x1c84(%rip), %rsi      # 0x305f
callq 0x10c0
movq %rax, %rdi
callq 0x1070
callq 0x12e6
leaq 0x10(%rsp), %rdi
callq 0x133d
callq 0x1320
leaq 0x10(%rsp), %rdi
callq 0x1776
movq 0x4bcb(%rip), %rbx      # 0x5fd8
leaq 0x1c52(%rip), %rsi      # 0x3066
movq %rbx, %rdi
callq 0x10c0
movq %rax, %rdi
callq 0x1070
leaq 0x1c42(%rip), %rsi      # 0x306d
leaq 0x10(%rsp), %rdi
callq 0x1835
leaq 0x1c37(%rip), %rsi      # 0x3073
movq %rbx, %rdi
callq 0x10c0
movq %rax, %rdi
callq 0x1070
leaq 0x1c2c(%rip), %rsi      # 0x307f
leaq 0x8(%rsp), %rdi
callq 0x1853
leaq 0x10(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x1c2c
leaq 0x8(%rsp), %rdi
callq 0x1896
movq 0x4b5b(%rip), %rdi      # 0x5fd8
leaq 0x1c01(%rip), %rsi      # 0x3085
callq 0x10c0
movq %rax, %rdi
callq 0x1070
leaq 0x18(%rsp), %rdi
callq 0x19f8
movq 0x4b36(%rip), %rbx      # 0x5fd8
leaq 0x1be8(%rip), %rsi      # 0x3091
movq %rbx, %rdi
callq 0x10c0
movq %rax, %rdi
callq 0x1070
leaq 0x1bad(%rip), %rsi      # 0x306d
leaq 0x10(%rsp), %rdi
callq 0x170e
leaq 0x1ba2(%rip), %rsi      # 0x3073
movq %rbx, %rdi
callq 0x10c0
movq %rax, %rdi
callq 0x1070
leaq 0x1b97(%rip), %rsi      # 0x307f
leaq 0x8(%rsp), %rdi
callq 0x170e
leaq 0x10(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x18b0
leaq 0x8(%rsp), %rdi
callq 0x1776
movq 0x4ac6(%rip), %rdi      # 0x5fd8
leaq 0x1b6c(%rip), %rsi      # 0x3085
callq 0x10c0
movq %rax, %rdi
callq 0x1070
leaq 0x10(%rsp), %rdi
callq 0x1776
movq 0x4aa1(%rip), %rbx      # 0x5fd8
leaq 0x1b5a(%rip), %rsi      # 0x3098
movq %rbx, %rdi
callq 0x10c0
movq %rax, %rdi
callq 0x1070
leaq 0x1b4a(%rip), %rsi      # 0x309f
leaq 0x38(%rsp), %r14
movq %r14, %rdi
callq 0x170e
movq %r14, %rdi
callq 0x1776
leaq 0x1b3a(%rip), %rsi      # 0x30ab
movq %rbx, %rdi
callq 0x10c0
movq %rax, %rdi
callq 0x1070
leaq 0x8(%rsp), %rbx
movq %rbx, %rdi
callq 0x18fe
leaq 0x10(%rsp), %rdi
movq %rbx, %rsi
xorl %edx, %edx
callq 0x1934
leaq 0x30(%rsp), %rdi
leaq 0x10(%rsp), %rsi
xorl %edx, %edx
callq 0x1934
leaq 0x30(%rsp), %rdi
callq 0x1776
leaq 0x10(%rsp), %rbx
movq %rbx, %rdi
callq 0x1776
leaq 0x8(%rsp), %rdi
callq 0x1776
movq 0x4a02(%rip), %r14      # 0x5fd8
leaq 0x1ad5(%rip), %rsi      # 0x30b2
movq %r14, %rdi
callq 0x10c0
movq %rax, %rdi
callq 0x1070
leaq 0x1b55(%rip), %r15      # 0x3149
movq %r14, %rdi
movq %r15, %rsi
callq 0x10c0
movq %rax, %rdi
callq 0x1070
movq %r14, %rdi
movq %r15, %rsi
callq 0x10c0
movq %rax, %rdi
callq 0x1070
leaq 0x1a98(%rip), %rsi      # 0x30b9
movq %r14, %rdi
callq 0x10c0
movq %rax, %rdi
callq 0x1070
xorps %xmm0, %xmm0
movaps %xmm0, (%rbx)
andq $0x0, 0x10(%rbx)
leaq 0x1a5c(%rip), %rsi      # 0x309f
leaq 0x10(%rsp), %rdi
callq 0x1972
leaq 0x10(%rsp), %rdi
callq 0x19ae
movq 0x497a(%rip), %rdi      # 0x5fd8
leaq 0x1a5b(%rip), %rsi      # 0x30c0
callq 0x10c0
movq %rax, %rdi
callq 0x1070
leaq 0x1a26(%rip), %rsi      # 0x309f
leaq 0x10(%rsp), %rdi
callq 0x19cf
leaq 0x18(%rsp), %rdi
callq 0x19f8
xorl %eax, %eax
addq $0x40, %rsp
popq %rbx
popq %r14
popq %r15
retq
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x19ae
jmp 0x1705
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x1776
jmp 0x16ba
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
jmp 0x16f1
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x1776
jmp 0x16ec
jmp 0x16e9
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x1896
jmp 0x16fb
jmp 0x16f8
jmp 0x16e9
jmp 0x16e9
jmp 0x16e9
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x1776
jmp 0x1705
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x19f8
movq %rbx, %rdi
callq 0x1140
nop