Razor Storm
Razor Storm

Reputation: 12336

Using && in a return statement causes it to become a type of int?

+ (id)checkWithBlock:(BOOL (^)(id))block 
{
  return [[[OCMBlockConstraint alloc] initWithConstraintBlock:block] autorelease];
}

[OCMArg checkWithBlock:^(id value) { return YES && YES; }];

I am passing in a return YES && YES to a block that returns a BOOL, and yet am getting this error:

Incompatible block pointer types sending 'int (^)(__strong id)' to parameter of type 'BOOL (^)(__strong id)'

Upvotes: 2

Views: 77

Answers (2)

Amin Negm-Awad
Amin Negm-Awad

Reputation: 16660

There is an answer and there is a good comment. However, we have to put things together to understand that:

A. In C the result of a logical and operation is an int. From the standard (ISO/IEC 9899:TC3):

Semantics The && operator shall yield 1 if both of its operands compare unequal to 0; otherwise, it yields 0. The result has type int.

B. Someone at Apple decided to have inferred types for blocks and stronger typing. This is a bad idea for C, because C does not support inferred types and is weakly typed. It solves the category of problems you have with implicit (or explicit) castings (weak typing), not with type inference and type strength. So the type strength of blocks does not fit for C.

C. Solution #1 (old): The original solution was, to explicitly cast the return value:

return (BOOL)(YES && YES);

D. Solution #2 (new): Later that many developers complained Apple for having un-C-ish strong typing combined with type inference for blocks that Apple introduced an explicit return type for blocks as in remus' answer. If you have such an explicit type, return expressions are implicitly casted to that type.


Z. The funny part of the story: Even Apple failed with that inferred types they try it again in Swift. And there it is much more complex and obfuscated if you have more than 1+2. One of the "cool feature you should use sparingly" stuff in Swift.

Upvotes: 1

brandonscript
brandonscript

Reputation: 72965

You're missing the BOOL declaration when calling the block method. If you use Xcode's autocomplete, it should create this for you:

[OCMArg checkWithBlock:^BOOL(id value) {
    return YES && YES;
}];

Upvotes: 3

Related Questions