Como otros han dicho, la razón por la que está recibiendo el error es que e0 || e1
devuelve un int
independientemente de los tipos de e0
y e1
. Dado que el compilador infiere el tipo de devolución de bloque basado en la declaración (s) return
, tiene un bloque que devuelve int
y está intentando asignarlo a una variable de bloque cuyo tipo de devolución de bloque es BOOL
.
yo personalmente prefiero esta sintaxis:
BoolBlock bar = ^BOOL { return YES || NO };
para evitar el error, por lo que es claro que el tipo de retorno bloque es BOOL
. El valor de r, un literal de bloque, se entiende como un bloque cuyo tipo de devolución es BOOL
y el compilador aplica las conversiones de C habituales.
En cuanto a por qué sucede esto, es una decisión de diseño, aunque no parece estar documentado explícitamente. Los bloques son una nueva función de idioma. Los diseñadores de compiladores han decidido que deberían tener una semántica más estricta en bloques, es decir, la asignación de tipos de punteros de bloque debe tener tipos estrictamente coincidentes, y refuerzan esta semántica más estricta cuando asignan un bloque a una variable de bloque independientemente del valor r un puntero de bloque o un literal de bloque.
Dado que no existe un estándar ISO/IEC que cubra bloques en C o C++, los diseñadores de compiladores son libres de tomar estas decisiones. Apple ha enviado bloques al ISO/IEC JTC1/SC22/WG14 como WG14/N1370 y WG14/N1451 y, si lo aceptan, este comportamiento (o alguna variante del mismo) debe estandarizarse y documentarse.
El código fuente de Clang tiene un comentario que indica que la asignación de punteros de bloque es más estricta que la asignación de punteros a funciones.
Les he preguntado personalmente acerca de esto.
Entonces, ¿por qué algo como '- (BOOL) foo {return SÍ || NO; } 'compilar? En otras palabras, ¿por qué importa la distinción entre entero y [BOOL] (http://stackoverflow.com/questions/541289) en el caso de bloque y no en el de la función? – zoul
@zoul: la función tiene un tipo de devolución explícita, por lo que la int se convertirá implícitamente en BOOL. Pero el bloque que se crea no tiene un tipo de devolución explícito, por lo que infiere su tipo de devolución de la declaración de devolución (esta es una habilidad especial que tienen los bloques). Estás devolviendo un int, por lo que infiere que el bloque devuelve un int. Solo entonces, después de que el tipo del bloque se haya inferido por completo, el compilador verifica ese tipo con el tipo de la variable a la que lo está asignando, por lo que obtiene una discrepancia de tipo. – Chuck