Macro to auto box (primitives) if it's not NSObject

Viewed 82

I have this macro that detects if a variable is an object:

#define IS_OBJECT(x) ( strchr("@#", @encode(typeof(x))[0]) != NULL )
#define AUTO_BOX(x) IS_OBJECT(x) ? x : @(x)

I wanted to simplify my workflow by auto box any primitives so that I can quickly do something like this:

BOOL v1 = YES;
id v2 = [[NSObject alloc] init];
NSLog(@"%@ %@", AUTO_BOX(v1), AUTO_BOX(v2));
//the @"%@ %@" format is non-changeable, I can't change them to @"%d %@" or @"%x %@"

This of course will throw error for v2 since it's an object:

 error: illegal type 'id' used in a boxed expression

What could I do to fix this?

1 Answers
CF_INLINE id auto_box_id_helper(const char *type, __strong id* val) {
    return *val;
}

CF_INLINE id auto_box_default_helper(const char *type, void *ptr) {
    return [NSValue valueWithBytes:ptr objCType:type];
}

#define AUTO_BOX(x) _Generic(\
        (x),\
        id: auto_box_id_helper,\
        default: auto_box_default_helper\
    )(\
        @encode(typeof((x))),\
        (typeof((x))[1]){(x)}\
    )

(typeof((x))[1]){(x)} is used instead of &(x), because you can't get pointer for example from &5. Also you will need expand this macro with NSNumber parameters, if you want get NSNumber instead of NSValue for numbers.

Related