Skip to content

Instantly share code, notes, and snippets.

@mikeash
Created September 29, 2010 01:52
Show Gist options
  • Save mikeash/602171 to your computer and use it in GitHub Desktop.
Save mikeash/602171 to your computer and use it in GitHub Desktop.
#import <Foundation/Foundation.h>
#import <pthread.h>
typedef void (^MyBlock)(void);
typedef void (*MyFunc)(void *);
static void Block(MyBlock block)
{
NSLog(@"Block called with %p", block);
}
static void Object(id obj, SEL sel)
{
NSLog(@"Object called with %p", obj);
}
static void Function(MyFunc func, void *userData, MyFunc destructor)
{
NSLog(@"Function called with %p", func);
}
#define TYPE_IS_TYPE(x, y) __builtin_types_compatible_p(x, y)
#define EXPR_IS_TYPE(expr, type) TYPE_IS_TYPE(__typeof__(expr), type)
#define CHOOSE(p, a, b) __builtin_choose_expr((p), (a), (b))
#define DEFAULT_TYPE(expr, type) CHOOSE(EXPR_IS_TYPE(expr, type), (expr), (type)NULL)
#define FUNCTYPE(x) __typeof__((__typeof__(x) *){ NULL })
#define THING_IMPL(x, y, z, ...) \
CHOOSE(EXPR_IS_TYPE(x, MyBlock), Block(DEFAULT_TYPE((x), MyBlock)), \
CHOOSE(EXPR_IS_TYPE(x, id), Object(DEFAULT_TYPE((x), id), (y)), \
CHOOSE(EXPR_IS_TYPE(x, MyFunc) || TYPE_IS_TYPE(FUNCTYPE(x), MyFunc), \
Function((MyFunc)(x), (y), (z)), \
assert(0))))
#define THING(x, ...) THING_IMPL(x, ## __VA_ARGS__, 0, 0)
static void f(void *x)
{
}
int main(int argc, char **argv)
{
NSString *obj = @"hello";
THING(^{});
THING(obj, @selector(abc));
THING(f, NULL, f);
THING(&f, NULL, &f);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment