Although the subject asks for replacement features, you really want to emulate what swizzle does. This means that you want to be able to call the same function name, but to have something else.
A pointer-only solution will not give you this behavior. If this is not important to you, then you should accept one of the available function pointers. If this is important to you, then you will need to introduce an abstraction layer. An abstraction can use function pointers under the hood (although there are other solutions).
The API for users of this interface will be:
void abstract_func_init (); typedef int abstract_func_type (); abstract_func_type * abstract_func_get (abstract_func_type *key); int abstract_func_set (abstract_func_type *key, abstract_func_type *behavior); extern int foo (); extern int bar ();
An implementation of such an interface might look like this:
static void insert (abstract_func_type *key, abstract_func_type **behavior) { } static abstract_func_type ** lookup (abstract_func_type *key) { } abstract_func_type * abstract_func_get (abstract_func_type *k) { abstract_func_type **f = lookup(k); if (f) return *f; return 0; } int abstract_func_set (abstract_func_type *k, abstract_func_type *p) { abstract_func_type **f = lookup(k); if (f) { *f = p; return 0; } return -ENOENT; } #define DEFINE_ABSTRACT_FUNC(func) \ static int static_##func (); \ static abstract_func_type *func##_ptr = static_##func; \ int func () { return func##_ptr(); } \ static int static_##func () DEFINE_ABSTRACT_FUNC(foo) { return puts("foo"); } DEFINE_ABSTRACT_FUNC(bar) { return puts("bar"); } void abstract_func_init () { insert(foo, &foo_ptr); insert(bar, &bar_ptr); }
Then the swap() that you originally presented in your post can be implemented as follows:
void swap (abstract_func_type *a, abstract_func_type *b) { abstract_func_type *ap = abstract_func_get(a); abstract_func_type *bp = abstract_func_get(b); abstract_func_set(a, bp); abstract_func_set(b, ap); }
Here is the program that calls swap() :
puts("before swap"); foo(); bar(); swap(foo, bar); puts("after swap"); foo(); bar();
And his conclusion will be:
before swap foo bar after swap bar foo
To automate the addition of abstract functions to the lookup table, you can enter an additional step in the build system called a script, which grep prints the lines DEFINE_ABSTRACT_FUNC and generates a new source file that had a function with insert() calls for each such line.
The full version of the layout can be found here .