Reputation: 16463
Say I've set up a macro expansion as follows...
#define WARN_START @"DANGER"
#define WARN_RESET @"THE COAST IS CLEAR"
#define WARN(x) WARN_START x WARN_RESET
INPUT WARN(@"*** Your boss is coming. ***")
OUTPUTDANGER *** Your boss is coming. *** THE COAST IS CLEAR
✅
and lets suppose I have a function…
NSString * WhosComing(void){ return @"*** Some fool. ***"; }
How can I pass the result of such a function to the macro, without first assigning it to a variable, i.e.
WARN(WhosComing())
ERRORexpected ')'
I've messed around with extra parenthesis, i.e.
#define WARN((x))
…. or ...WARN_START (x) WARN_RESET
but…
ERRORinvalid operands to binary expression
, etc.
as well as trying to pass the cuntion as a pointer, or something, i.e. WARN(&WhosComing())
, to no avail. I'm sure this is possible / straightforward… but I don't have a CS degree, so I never learned how.. Easy answer for someone?
Upvotes: 0
Views: 140
Reputation: 237010
Well, you can't have the result of the function inserted at compile-time, as obviously the function's result doesn't exist until it is executed. But you can do something like this:
#define WARN(x) [NSString stringWithFormat:@"%@ %@ %@", WARN_START, (x), WARN_RESET]
But that's no better than a function, is it? If the argument to the macro were a literal string, you could write it the way you want. But since the argument's value is not even known at compile time, there's not a whole lot you can do with it at the macro-expansion stage, so emitting an expression that will produce the value you want at run time is pretty much your only option.
Upvotes: 2
Reputation: 53000
You cannot do what you are attempting with a macro. It is a feature of the C language (and hence Objective-C, C++) that adjacent string literals are concatenated during compilation and this is extended for Objective-C to included NSString
literals.
Your macro expands to:
@"DANGER" @"*** Your boss is coming. ***" @"THE COAST IS CLEAR"
and the compiler then concatenates these 3 literals into 1.
However pass in your function and you get:
@"DANGER" WhosComing() @"THE COAST IS CLEAR"
which is invalid code.
There are various solutions; you could use a real function, inlining it if are really concerned over the cost of the function call:
NS_INLINE NSString *WARN(NSString *msg)
{
return [NSString stringWithFormat:@"%@%@%@", WARN_START, msg, WARN_RESET];
}
Upvotes: 3