// File: 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
subq $0x220, %rsp            # imm = 0x220
movl $0x0, -0x4(%rbp)
movq $0x0, -0x10(%rbp)
movq $0x0, -0x18(%rbp)
callq 0x2940
movq %rax, -0x20(%rbp)
xorl %eax, %eax
movl %eax, %edx
movq %rdx, -0x1a8(%rbp)
leaq -0x58(%rbp), %rdi
movq %rdi, -0x1b0(%rbp)
movq %rdx, %rsi
callq 0x2950
movq -0x1b0(%rbp), %rax
movq -0x1a8(%rbp), %rdx
movq %rax, -0x60(%rbp)
leaq -0x98(%rbp), %rdi
movq %rdx, %rsi
callq 0x2950
jmp 0x23ac
leaq -0x98(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0x10(%rbp), %rax
leaq -0x58(%rbp,%rax), %rsi
leaq -0xd0(%rbp), %rdi
callq 0x2070
jmp 0x23d1
movq -0x10(%rbp), %rax
leaq -0x98(%rbp,%rax), %rsi
leaq -0xf0(%rbp), %rdi
callq 0x2070
jmp 0x23eb
movq -0x60(%rbp), %rsi
movq -0x10(%rbp), %rax
addq %rax, %rsi
leaq -0xd0(%rbp), %rdi
callq 0x2030
jmp 0x2404
leaq 0x5e5(%rip), %rax       # 0x29f0
movq %rax, -0x100(%rbp)
movq $0x0, -0xf8(%rbp)
leaq 0x5fc(%rip), %rcx       # 0x2a20
movq %rcx, -0x110(%rbp)
movq $0x0, -0x108(%rbp)
movq %rcx, -0x100(%rbp)
movq $0x0, -0xf8(%rbp)
movq %rax, -0x110(%rbp)
movq $0x0, -0x108(%rbp)
xorl %eax, %eax
movl %eax, %edx
leaq -0x148(%rbp), %rdi
movq %rdx, %rsi
callq 0x2950
jmp 0x246f
leaq -0x148(%rbp), %rdi
callq 0x29f0
movb %al, -0x1b1(%rbp)
jmp 0x2483
movb -0x1b1(%rbp), %al
movb %al, -0x149(%rbp)
movq -0x110(%rbp), %rax
movq %rax, -0x1c8(%rbp)
movq -0x108(%rbp), %rdx
leaq -0x148(%rbp), %rcx
addq %rdx, %rcx
movq %rcx, -0x1c0(%rbp)
andq $0x1, %rax
cmpq $0x0, %rax
je 0x2567
movq -0x1c8(%rbp), %rcx
movq -0x1c0(%rbp), %rax
movq (%rax), %rax
subq $0x1, %rcx
movq (%rax,%rcx), %rax
movq %rax, -0x1d0(%rbp)
jmp 0x2575
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa0(%rbp)
movl %eax, -0xa4(%rbp)
jmp 0x27bd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa0(%rbp)
movl %eax, -0xa4(%rbp)
jmp 0x27b1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa0(%rbp)
movl %eax, -0xa4(%rbp)
jmp 0x27a5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa0(%rbp)
movl %eax, -0xa4(%rbp)
jmp 0x2799
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa0(%rbp)
movl %eax, -0xa4(%rbp)
leaq -0x148(%rbp), %rdi
callq 0x2bd0
jmp 0x2799
movq -0x1c8(%rbp), %rax
movq %rax, -0x1d0(%rbp)
movq -0x1c0(%rbp), %rdi
movq -0x1d0(%rbp), %rax
callq *%rax
movb %al, -0x1d1(%rbp)
jmp 0x258d
movb -0x1d1(%rbp), %al
movb %al, -0x14a(%rbp)
movq -0x60(%rbp), %rcx
movq -0x100(%rbp), %rax
movq %rax, -0x1e8(%rbp)
movq -0xf8(%rbp), %rdx
addq %rdx, %rcx
movq %rcx, -0x1e0(%rbp)
andq $0x1, %rax
cmpq $0x0, %rax
je 0x25e8
movq -0x1e8(%rbp), %rcx
movq -0x1e0(%rbp), %rax
movq (%rax), %rax
subq $0x1, %rcx
movq (%rax,%rcx), %rax
movq %rax, -0x1f0(%rbp)
jmp 0x25f6
movq -0x1e8(%rbp), %rax
movq %rax, -0x1f0(%rbp)
movq -0x1e0(%rbp), %rdi
movq -0x1f0(%rbp), %rax
callq *%rax
movb %al, -0x1f1(%rbp)
jmp 0x260e
movb -0x1f1(%rbp), %al
movb %al, -0x149(%rbp)
leaq 0x42f(%rip), %rax       # 0x2a50
movq %rax, -0x160(%rbp)
movq $0x0, -0x158(%rbp)
xorl %eax, %eax
movl %eax, %edx
leaq -0x58(%rbp), %rdi
movq %rdx, %rsi
callq 0x2a50
movb %al, -0x1f2(%rbp)
jmp 0x264b
movb -0x1f2(%rbp), %al
movb %al, -0x149(%rbp)
movq -0x160(%rbp), %rax
movq %rax, -0x208(%rbp)
movq -0x158(%rbp), %rdx
leaq -0x58(%rbp), %rcx
addq %rdx, %rcx
movq %rcx, -0x200(%rbp)
andq $0x1, %rax
cmpq $0x0, %rax
je 0x26a6
movq -0x208(%rbp), %rcx
movq -0x200(%rbp), %rax
movq (%rax), %rax
subq $0x1, %rcx
movq (%rax,%rcx), %rax
movq %rax, -0x210(%rbp)
jmp 0x26b4
movq -0x208(%rbp), %rax
movq %rax, -0x210(%rbp)
movq -0x200(%rbp), %rdi
movq -0x210(%rbp), %rax
xorl %ecx, %ecx
movl %ecx, %edx
movq %rdx, %rsi
callq *%rax
movb %al, -0x211(%rbp)
jmp 0x26d3
movb -0x211(%rbp), %al
movb %al, -0x14a(%rbp)
leaq 0x36a(%rip), %rax       # 0x2a50
movq %rax, -0x170(%rbp)
movq $0x0, -0x168(%rbp)
leaq -0x58(%rbp), %rdi
xorl %esi, %esi
callq 0x2a90
jmp 0x2705
leaq -0x58(%rbp), %rdi
movl $0x4, %esi
callq 0x2a90
jmp 0x2715
leaq 0x2d4(%rip), %rax       # 0x29f0
movq %rax, -0x1a0(%rbp)
movq $0x0, -0x198(%rbp)
leaq -0x190(%rbp), %rdi
leaq -0x1a0(%rbp), %rsi
callq 0x2b10
movl $0x0, -0x4(%rbp)
leaq -0x190(%rbp), %rdi
callq 0x2bb0
leaq -0x148(%rbp), %rdi
callq 0x2bd0
leaq -0xf0(%rbp), %rdi
callq 0x2090
leaq -0xd0(%rbp), %rdi
callq 0x2090
leaq -0x98(%rbp), %rdi
callq 0x2bd0
leaq -0x58(%rbp), %rdi
callq 0x2bd0
movl -0x4(%rbp), %eax
addq $0x220, %rsp            # imm = 0x220
popq %rbp
retq
leaq -0xf0(%rbp), %rdi
callq 0x2090
leaq -0xd0(%rbp), %rdi
callq 0x2090
leaq -0x98(%rbp), %rdi
callq 0x2bd0
leaq -0x58(%rbp), %rdi
callq 0x2bd0
movq -0xa0(%rbp), %rdi
callq 0x2120
nopw %cs:(%rax,%rax)
nopl (%rax)