// File: klmr[P]multifunction/example.cpp
// Function: main
int main() {
    static_assert(
        std::is_same<
            util::multifunction<void(int)>::argument_type,
            int
        >::value,
        "util::multifunction member types are wrong");

    util::multifunction<void(int)> event;

    cout << "Adding f, g, h\n";
    auto f_tok = event += f;
    auto g_tok = event += g();
    auto h_tok = event += h;

    event(1);

    cout << "\nRemoving g\n";
    event -= g_tok;
    event(2);

    cout << "\nRemoving h\n";
    event -= h_tok;
    event(3);

    cout << "\nRemoving g (again!)\n";
    event -= g_tok;
    event(4);

    cout << "\nRemoving f\n";
    event -= f_tok;
    event(5);

    cout << "\nOnce more, with lambdas\n";
    event += [](int n) { cout << "[](" << n << ")\n"; };
    event += [=](int n) { cout << "[=](" << n << ")\n"; };
    event += [&](int n) { cout << "[&](" << n << ")\n"; };
    int n = 6;
    event(n);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
leaq -0x30(%rbp), %rdi
callq 0x23c0
movq 0x9cbd(%rip), %rdi      # 0xafd8
leaq 0x4d6c(%rip), %rsi      # 0x608e
callq 0x10b0
jmp 0x1329
leaq -0xc0(%rip), %rsi       # 0x1270
leaq -0x30(%rbp), %rdi
callq 0x23f0
movl %eax, -0x90(%rbp)
jmp 0x1341
movl -0x90(%rbp), %eax
movl %eax, -0x40(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x2420
movl %eax, -0x94(%rbp)
jmp 0x135b
movl -0x94(%rbp), %eax
movl %eax, -0x44(%rbp)
leaq -0xbb(%rip), %rsi       # 0x12b0
leaq -0x30(%rbp), %rdi
callq 0x2450
movl %eax, -0x98(%rbp)
jmp 0x137c
movl -0x98(%rbp), %eax
movl %eax, -0x4c(%rbp)
movl $0x1, -0x50(%rbp)
leaq -0x30(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0x2480
jmp 0x139b
movq 0x9c36(%rip), %rdi      # 0xafd8
leaq 0x4cf5(%rip), %rsi      # 0x609e
callq 0x10b0
jmp 0x13b0
movl -0x44(%rbp), %eax
movl %eax, -0x54(%rbp)
movl -0x54(%rbp), %esi
leaq -0x30(%rbp), %rdi
callq 0x24b0
jmp 0x13c4
movl $0x2, -0x58(%rbp)
leaq -0x30(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x2480
jmp 0x13da
movq 0x9bf7(%rip), %rdi      # 0xafd8
leaq 0x4cc3(%rip), %rsi      # 0x60ab
callq 0x10b0
jmp 0x13ef
movl -0x4c(%rbp), %eax
movl %eax, -0x5c(%rbp)
movl -0x5c(%rbp), %esi
leaq -0x30(%rbp), %rdi
callq 0x24b0
jmp 0x1403
movl $0x3, -0x60(%rbp)
leaq -0x30(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x2480
jmp 0x1419
movq 0x9bb8(%rip), %rdi      # 0xafd8
leaq 0x4c91(%rip), %rsi      # 0x60b8
callq 0x10b0
jmp 0x142e
movl -0x44(%rbp), %eax
movl %eax, -0x64(%rbp)
movl -0x64(%rbp), %esi
leaq -0x30(%rbp), %rdi
callq 0x24b0
jmp 0x1442
movl $0x4, -0x68(%rbp)
leaq -0x30(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x2480
jmp 0x1458
movq 0x9b79(%rip), %rdi      # 0xafd8
leaq 0x4c68(%rip), %rsi      # 0x60ce
callq 0x10b0
jmp 0x146d
movl -0x40(%rbp), %eax
movl %eax, -0x6c(%rbp)
movl -0x6c(%rbp), %esi
leaq -0x30(%rbp), %rdi
callq 0x24b0
jmp 0x1481
movl $0x5, -0x70(%rbp)
leaq -0x30(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x2480
jmp 0x1497
movq 0x9b3a(%rip), %rdi      # 0xafd8
leaq 0x4c36(%rip), %rsi      # 0x60db
callq 0x10b0
jmp 0x14ac
leaq -0x30(%rbp), %rdi
callq 0x1550
movl %eax, -0x9c(%rbp)
jmp 0x14bd
movl -0x9c(%rbp), %eax
movl %eax, -0x78(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x1580
movl %eax, -0xa0(%rbp)
jmp 0x14d7
movl -0xa0(%rbp), %eax
movl %eax, -0x80(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x15b0
movl %eax, -0xa4(%rbp)
jmp 0x14f1
movl -0xa4(%rbp), %eax
movl %eax, -0x88(%rbp)
movl $0x6, -0x8c(%rbp)
leaq -0x30(%rbp), %rdi
leaq -0x8c(%rbp), %rsi
callq 0x24e0
jmp 0x1519
leaq -0x30(%rbp), %rdi
callq 0x2510
xorl %eax, %eax
addq $0xb0, %rsp
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x2510
movq -0x38(%rbp), %rdi
callq 0x1110
nopl (%rax,%rax)