// File: iZhangHui[P]CppPrimer/CH16_TemplatesAndGenericProgramming/exercises/ex16_47.cc
// Function: main
int main(int argc, char const *argv[])
{
	int i = 0, j = 0, k = 0, l = 0;
	cout << i << " " << j << " " << k << " " << l << endl;

	f(42, i);        // f changes its argument i
	flip1(f, j, 42); // f called through flip1 leaves j unchanged
	flip2(f, k, 42); // ok: k is changed
	cout << "=========================================" << endl;
	g(1, i);
	flip(g, i, 42);  // ok: rvalue-ness of the third argument is preserved
	cout << i << " " << j << " " << k << " " << l << endl;
	cout << "=========================================" << endl;

	// test for lvalue reference
	string s1;
	string s2;
	flip(func_lvalue, s1, s2);
	cout << s1 << " " << s2 << endl;

	// test for rvalue reference
	flip(func_rvalue, 99, 88);

	// void flip1(F, T1, T2) [with F = void (*)(int&&, int&&); T1 = int; T2 = int]’:
	// ex16_47.cc:88:27:   required from here
	// ex16_47.cc:28:3: error: cannot bind ‘int’ lvalue to ‘int&&’
	// f(t2, t1);
	// ^
	// flip1(func_rvalue, 99, 88);

	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xf0, %rsp
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl $0x0, -0x14(%rbp)
movl $0x0, -0x18(%rbp)
movl $0x0, -0x1c(%rbp)
movl $0x0, -0x20(%rbp)
movl -0x14(%rbp), %esi
movq 0x2af9(%rip), %rdi      # 0x3fd8
movq %rdi, -0xb0(%rbp)
callq 0x10f0
movq %rax, %rdi
leaq 0xb0f(%rip), %rsi       # 0x2004
movq %rsi, -0xb8(%rbp)
callq 0x1080
movq %rax, %rdi
movl -0x18(%rbp), %esi
callq 0x10f0
movq -0xb8(%rbp), %rsi
movq %rax, %rdi
callq 0x1080
movq %rax, %rdi
movl -0x1c(%rbp), %esi
callq 0x10f0
movq -0xb8(%rbp), %rsi
movq %rax, %rdi
callq 0x1080
movq %rax, %rdi
movl -0x20(%rbp), %esi
callq 0x10f0
movq %rax, %rdi
movq 0x2a7e(%rip), %rsi      # 0x3fc8
movq %rsi, -0xa0(%rbp)
callq 0x10b0
movl $0x2a, %edi
movl %edi, -0xcc(%rbp)
leaq -0x14(%rbp), %rsi
movq %rsi, -0xc0(%rbp)
callq 0x1250
movl -0xcc(%rbp), %edx
leaq -0x32e(%rip), %rdi      # 0x1250
movq %rdi, -0xc8(%rbp)
movl -0x18(%rbp), %esi
callq 0x18d0
movq -0xc8(%rbp), %rdi
movl $0x2a, -0x24(%rbp)
leaq -0x1c(%rbp), %rsi
leaq -0x24(%rbp), %rdx
callq 0x1900
movq -0xb0(%rbp), %rdi
leaq 0xa5d(%rip), %rsi       # 0x2013
movq %rsi, -0xa8(%rbp)
callq 0x1080
movq -0xa0(%rbp), %rsi
movq %rax, %rdi
callq 0x10b0
movq -0xc0(%rbp), %rsi
movl $0x1, -0x28(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x12b0
movq -0xc0(%rbp), %rsi
leaq -0x346(%rip), %rdi      # 0x12b0
movl $0x2a, -0x2c(%rbp)
leaq -0x2c(%rbp), %rdx
callq 0x1930
movq -0xb0(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0x10f0
movq -0xb8(%rbp), %rsi
movq %rax, %rdi
callq 0x1080
movq %rax, %rdi
movl -0x18(%rbp), %esi
callq 0x10f0
movq -0xb8(%rbp), %rsi
movq %rax, %rdi
callq 0x1080
movq %rax, %rdi
movl -0x1c(%rbp), %esi
callq 0x10f0
movq -0xb8(%rbp), %rsi
movq %rax, %rdi
callq 0x1080
movq %rax, %rdi
movl -0x20(%rbp), %esi
callq 0x10f0
movq -0xa0(%rbp), %rsi
movq %rax, %rdi
callq 0x10b0
movq -0xb0(%rbp), %rdi
movq -0xa8(%rbp), %rsi
callq 0x1080
movq -0xa0(%rbp), %rsi
movq %rax, %rdi
callq 0x10b0
leaq -0x50(%rbp), %rdi
movq %rdi, -0x98(%rbp)
callq 0x10d0
leaq -0x70(%rbp), %rdi
movq %rdi, -0x90(%rbp)
callq 0x10d0
movq -0x98(%rbp), %rsi
movq -0x90(%rbp), %rdx
leaq -0x3b9(%rip), %rdi      # 0x1310
callq 0x1960
jmp 0x16d0
movq 0x2901(%rip), %rdi      # 0x3fd8
leaq -0x50(%rbp), %rsi
callq 0x1070
movq %rax, -0xd8(%rbp)
jmp 0x16e9
movq -0xd8(%rbp), %rdi
leaq 0x90d(%rip), %rsi       # 0x2004
callq 0x1080
movq %rax, -0xe0(%rbp)
jmp 0x1705
movq -0xe0(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x1070
movq %rax, -0xe8(%rbp)
jmp 0x171e
movq -0xe8(%rbp), %rdi
movq 0x289c(%rip), %rsi      # 0x3fc8
callq 0x10b0
jmp 0x1733
movl $0x63, -0x80(%rbp)
movl $0x58, -0x84(%rbp)
leaq -0x3fb(%rip), %rdi      # 0x1350
leaq -0x80(%rbp), %rsi
leaq -0x84(%rbp), %rdx
callq 0x1990
jmp 0x175d
movl $0x0, -0x4(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x1040
leaq -0x50(%rbp), %rdi
callq 0x1040
movl -0x4(%rbp), %eax
addq $0xf0, %rsp
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x1040
leaq -0x50(%rbp), %rdi
callq 0x1040
movq -0x78(%rbp), %rdi
callq 0x1100
nopl (%rax)