Function pointers are another kind of pointer. They point to, well, functions. The syntax for a function pointer is what we've seen with std::function, but with (*name) in the middle.

int main() {
    void (*fp)();

Yes, that really does declare a variable/argument. Imagine what you get if that function pointer returns another, or returns a pointer to an array, or a pointer to a function pointer, or, well, it's best not to think about it. Function pointers are what C did, since templates and std::function don't exist in C.

Function pointers can be created from functions.

void f() {}
int main() {
    void (*fp)() = f;

You can call function pointers directly.

    f(); // OK

But here's an interesting artifact- when you dereference a function pointer, you get a function- which immediately decays back into a function pointer.

    (******************fp)(); // wat
}

The important thing to know about function pointers is that they can be functions, more functions, and only functions. Instantiations of function templates, or static member functions also count. But no member functions, no function objects, no lambdas, no nothing. You cannot convert any kind of member or stateful function to a function pointer. Lambdas can be converted to a function pointer as long as they capture nothing. This means that if you have a legacy C function which takes a function pointer and you want to pass a stateful function to it, you have only three choices.

The first is the void* arg idiom. Even in C it was recognized that this was a problem, and most C APIs which deal with function pointers allow for a void* argument- where the function taking the function pointer takes a void pointer, which is simply passed on to the function pointer. This can be used for a pointer to, say, a class instance, std::function, or whatever. For example,

void f(void(*fp)(void*), void* p) {
    fp(p);
}
void mah_func(void* p) {
    reinterpret_cast<my_class*>(p)->func();
}
int main() {
    my_class m;
    f(mah_func, &m);
}

This is common but not global. Another solution is the "throw up" hack. This is the most generic of the solutions, but also the most disgusting. It abuses exceptions.

void f(void(*fp)()) { fp(); }
void mah_func() {
    try {
        throw;
    } catch(my_class* m) {
        m->func();
    }
}
int main() {
    my_class m;
    try {
        throw &m;
    } catch(my_class* p) {
        f(mah_func);
    }
}

Amazingly, this is actually well-defined behaviour. But it's a rather nasty abuse. Finally, you can use a thread-local stack of objects, which you can globally access. The problem is knowing what type the stack should be of, and thread_local support right now is not the best. If you were super desperate, you could grab a JIT library like LLVM and JIT a thunk. But that requires a huge library, and is reserved for the truly desperate.