// File: /workspace/github_cpp_makefile_star2_O1/iZhangHui[P]CppPrimer/CH19_SpecializedToolsAndTechniques/examples/useScreen.cc
// Function: main
int main ()
{
	// pdata can point to a string member of a const (or nonconst) Screen
	const string Screen::*pdata;  // uninitialized
	pdata = &Screen::contents;    // points to the contents member
	auto pdata2 = &Screen::contents; // equivalent declaration

	// data() returns a pointer to the contents member of class Screen
	const string Screen::*pdata3 = Screen::data();
	
	// Screen objects
	Screen myScreen, *pScreen = &myScreen;
	const Screen cScreen, *pcScreen = &cScreen;

	// .* dereferences pdata to fetch the contents member 
	// from the object myScreen
	auto str = myScreen.*pdata;  // s is a string
	auto cstr = cScreen.*pdata;  // c is a const string
	
	// ->* dereferences pdata to fetch contents 
	// from the object to which pScreen points
	str = pScreen->*pdata;  
	
	// pmf is a pointer that can point to a Screen member function 
	// that takes no arguments, returns a char, and is const
	// that returns a char and takes no arguments
	auto pmf = &Screen::get_cursor;
	char (Screen::*pmf2)() const = &Screen::get; // same type as pmf
	
	pmf = &Screen::get; // which version of get deduced from type of pmf
	pmf2 = &Screen::get_cursor;
	
	Screen s;
	char c1 = s.get_cursor(); // gets character at the cursor directly
	char c2 = (s.*pmf2)();    // calls get_cursor indirectly through pmf2
	
	// call the function to which pmf points 
	// on the object to which pScreen points
	c1 = (pScreen->*pmf)();  
	
	// pmf3 points to the two-parameter version of get
	char (Screen::*pmf3)(Screen::pos, Screen::pos) const = &Screen::get;
	c1 = myScreen.get(0,0);     // call two-parameter version of get 
	c2 = (myScreen.*pmf3)(0,0); // equivalent call to get
	
	// Op is a type that can point to a member function of Screen 
	// that returns a char and takes two pos arguments
	using Op = char (Screen::*)(Screen::pos, Screen::pos) const;
	// equivalent declaration of Op using a typedef
	typedef char (Screen::*Op)(Screen::pos, Screen::pos) const;

	Op get = &Screen::get; // get points to the get member of Screen
	
	myScreen.move(Screen::HOME);  // invokes myScreen.home
	myScreen.move(Screen::DOWN);  // invokes myScreen.down

	// bind an object of type function to a pointer to member
	function<char (const Screen*)> f = &Screen::get_cursor;

	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xe8, %rsp
leaq -0xc8(%rbp), %r12
movq %r12, -0x10(%r12)
leaq -0xd8(%rbp), %rbx
movq %rbx, %rdi
xorl %esi, %esi
movl $0x20, %edx
callq 0x10f0
xorps %xmm0, %xmm0
movups %xmm0, 0x20(%rbx)
movq $0x0, 0x30(%rbx)
leaq -0x90(%rbp), %r13
movq %r13, -0x10(%r13)
leaq -0xa0(%rbp), %rdi
xorl %esi, %esi
movl $0x20, %edx
callq 0x10f0
xorps %xmm0, %xmm0
movups %xmm0, -0x80(%rbp)
movq $0x0, -0x70(%rbp)
leaq -0x38(%rbp), %rax
movq %rax, -0x10(%rax)
movq -0xd8(%rbp), %rsi
movq -0xd0(%rbp), %rdx
addq %rsi, %rdx
leaq -0x48(%rbp), %rdi
callq 0x1704
leaq -0x58(%rbp), %rax
movq %rax, -0x10(%rax)
movq -0xa0(%rbp), %rsi
movq -0x98(%rbp), %rdx
addq %rsi, %rdx
leaq -0x68(%rbp), %rdi
callq 0x1704
leaq -0x48(%rbp), %rdi
movq %rbx, %rsi
callq 0x1070
leaq -0x100(%rbp), %r14
movq %r14, -0x10(%r14)
leaq -0x110(%rbp), %rdi
xorl %esi, %esi
movl $0x20, %edx
callq 0x10f0
xorps %xmm0, %xmm0
movups %xmm0, -0xf0(%rbp)
movq $0x0, -0xe0(%rbp)
leaq 0x2c43(%rip), %r15      # 0x40c0
movq (%r15), %rax
movq 0x8(%r15), %rdi
addq %rbx, %rdi
testb $0x1, %al
je 0x1493
movq (%rdi), %rcx
movq -0x1(%rcx,%rax), %rax
callq *%rax
movq 0x40(%r15), %rax
addq 0x48(%r15), %rbx
testb $0x1, %al
je 0x14a9
movq (%rbx), %rcx
movq -0x1(%rcx,%rax), %rax
movq %rbx, %rdi
callq *%rax
movq -0x110(%rbp), %rdi
cmpq %r14, %rdi
je 0x14c9
movq -0x100(%rbp), %rsi
incq %rsi
callq 0x10d0
movq -0x68(%rbp), %rdi
leaq -0x58(%rbp), %rax
cmpq %rax, %rdi
leaq -0x38(%rbp), %rbx
je 0x14e6
movq -0x58(%rbp), %rsi
incq %rsi
callq 0x10d0
movq -0x48(%rbp), %rdi
cmpq %rbx, %rdi
je 0x14fb
movq -0x38(%rbp), %rsi
incq %rsi
callq 0x10d0
movq -0xa0(%rbp), %rdi
cmpq %r13, %rdi
je 0x1516
movq -0x90(%rbp), %rsi
incq %rsi
callq 0x10d0
movq -0xd8(%rbp), %rdi
cmpq %r12, %rdi
je 0x1531
movq -0xc8(%rbp), %rsi
incq %rsi
callq 0x10d0
xorl %eax, %eax
addq $0xe8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x1547
movq %rax, %rbx
jmp 0x1579
movq %rax, %rbx
jmp 0x1592
movq %rax, %rbx
jmp 0x15ab
movq %rax, %rbx
jmp 0x15c6
movq %rax, %rbx
movq -0x110(%rbp), %rdi
cmpq %r14, %rdi
je 0x1579
movq -0x100(%rbp), %rsi
incq %rsi
callq 0x10d0
movq -0x68(%rbp), %rdi
leaq -0x58(%rbp), %rax
cmpq %rax, %rdi
je 0x1592
movq -0x58(%rbp), %rsi
incq %rsi
callq 0x10d0
movq -0x48(%rbp), %rdi
leaq -0x38(%rbp), %rax
cmpq %rax, %rdi
je 0x15ab
movq -0x38(%rbp), %rsi
incq %rsi
callq 0x10d0
movq -0xa0(%rbp), %rdi
cmpq %r13, %rdi
je 0x15c6
movq -0x90(%rbp), %rsi
incq %rsi
callq 0x10d0
movq -0xd8(%rbp), %rdi
cmpq %r12, %rdi
je 0x15e1
movq -0xc8(%rbp), %rsi
incq %rsi
callq 0x10d0
movq %rbx, %rdi
callq 0x1120
nop