Peut-etre que tout simplement chacha à raison, devant l'ambiguà¯té que représente [item childAtIndex:0], le compilo ne sait que choisir car il existe plusieurs méthodes childAtIndex: pour le type id (celle de Truc, celles présentes dans le fundation framework).
La seule solution serait donc de renommer childAtIndex: en bidule: ou alors de caster...
Dans ta méthode - (id) outlineView: (NSOutlineView *)outlineView child: (NSInteger)anIndex ofItem: (id)anItem { return (anItem) ? [anItem childAtIndex: anIndex] : [dataSource childAtIndex: anIndex]; } Le problème est que [dataSource childAtIndex:anIndex] possède un type bien défini par le fait que dataSource est parfaitement déclaré dans l'instance. Alors que [anItem childAtIndex: anIndex] est de type indéterminé donc id.
- Pour un opérateur ternaire, une comparaison est faite entre les deux types de l'alternative (peut-être simplement pour attribuer un type au résultat de l'expression que constitue l'ensemble de l'opérateur ternaire). Le warning indique simplement la différence de type. Ce qui trompe ici est que l'on pense que anItem va être de même type (ou quasiment) que dataSource, mais à la compilation, ceci n'a évidemment pas de sens.
- En changeant childAtIndex: par biduleAtIndex: , le compilateur vérifie dans toutes les interfaces disponibles si il y a plusieurs méthodes biduleAIndex: , et n'en voyant qu'une, il ne met pas le warning.
- L'exemple qui ne présente pas de warning : return ( item )? [item bidule] :[NSString stringWithFormat:@Hello World %d,2009]; vient sans doute de la particularité dans la représentation des NSString en NSCFString.
Trouvant que ce post était un peu court sur le fond, j'ai fait quelques essais en C : Quelles sont les lignes du code ci-dessous où l'opérateur ternaire provoque un Warning (-Wall -Wextra) de la part de gcc ?
#include <stdio.h> int val(int n, double x) { return n ? : x ; }
int main(void){ double x=2009.; int n=2; char c= x? n : x ; void * p = n ? &n : (void*)&x ; void * q = n ? &n : &x ; printf( n? &n : (void*) " Hello\n"); return 0; }
[move]Je ramasse les copies dans 5 minutes. [/move]
Oui, mais toi qui es tout frais sur le coup, reconnais quand même [move][size=13pt]Il est vraiment bizarre[/size][/move] [move] [glow=red,2,300][size=16pt] ce Warning [/size][/glow] [/move]<br />[move][size=13pt]Hein ?[/size][/move]
La réponse : Le choix du warning pour l'opérateur ternaire est obscur
Pourquoi mettre un warning pour void * q = n ? &n : &x ; et ne pas en mettre pour void * p = n ? &n : (void*)&x ;. Ce choix peu logique en première analyse, et même en deuxième, est le schéma qui nous a fait écrire 4 pages sur le sujet, et il y a effectivement de quoi s'en plaindre :P
On n'en met pas pour char c= x? n : x ; . Ok les promotions ou casts automatiques vont faire le travail.
On n'a pas de warning pour int val(int n, double x) { return n ? : x ;}, admettons mais il n'y en n'a pas pour printf( n? &n : (void*) " Hello\n");. Les warnings sont là pour prévenir d'erreurs potentielles, mêmes absurdes ( surtout absurdes ).
dans 1231152486:
Quelles sont les lignes du code ci-dessous où l'opérateur ternaire provoque un Warning (-Wall -Wextra) de la part de gcc ? #include <stdio.h> int val(int n, double x) { return n ? : x ; }
int main(void){ double x=2009.; int n=2; char c= x? n : x ; void * p = n ? &n : (void*)&x ; void * q = n ? &n : &x ; printf( n? &n : (void*) " Hello\n"); return 0; }
since C does not have a type hierarchy for pointer types, pointer operands may only be used if they are of the same type (ignoring type qualifiers) or one is void or NULL.
void* fait donc figure d'exception apparemment. ça n'explique pas pourquoi @... fait pareil en obj-c, mais bon...
Réponses
return (anItem) ? [anItem childAtIndex: 0] : @does not exist; (pas de warning)
return (anItem) ? [anItem childAtIndex: 0] : (NSString *)@does not exist; (warning)
Là , c'est plus logique, la méthode renvoie (id) un type imprécis, et le cast (NSString*) mérite un warning.
Essai ==> pareil
@implementation Truc
-(Truc *) childAtIndex:(NSUInteger) n {
return self;
}
@end
=========================================
#import "Truc.h"
@interface TrucFils : Truc {
}
@end
#import "TrucFils.h"
@implementation TrucFils
-(TrucFils *) childAtIndex:(NSUInteger) n {
return self;
}
@end
=========================================
#import "AppController.h"
#import "Truc.h"
#import "TrucFils.h"
@implementation AppController
-(void) awakeFromNib {
}
-(id)string:(id) item{
return ( item )?
[item childAtIndex:0] : // renvoie un Truc *
[item childAtIndex:1];
}
-(IBAction) buttonAction:(id)sender {
TrucFils * truc=[[TrucFils alloc]init];
NSLog(@%@",[self string:nil]);
NSLog(@%@",[self string:0]);
NSLog(@%@",[self string:truc]);
}
@end
@implementation Truc
-(Truc *) childAtIndex:(NSUInteger) n {
return self;
}
@end
=========================================
#import "Truc.h"
@interface TrucFils : Truc {
}
@end
#import "TrucFils.h"
@implementation TrucFils
-(TrucFils *) childAtIndex:(NSUInteger) n {
return self;
}
@end
=========================================
#import "AppController.h"
#import "Truc.h"
#import "TrucFils.h"
@interface AppController : Object {
TrucFils *trucFils;
}
@end
@implementation AppController
- (id) init {
trucFils = [[TrucFils alloc] init];
}
-(void) awakeFromNib {
}
-(id)string:(id) item{
return ( item )?
[item childAtIndex:0] : // renvoie un Truc *
[trucFils childAtIndex:1];
}
-(IBAction) buttonAction:(id)sender {
Truc * truc = [[Truc alloc]init];
NSLog(@%@",[self string:nil]);
NSLog(@%@",[self string:truc]);
}
@end
Le premier qui sait pourquoi a gagné !!
Quelle comparaison ? celle de item avec nil l'idée d'Ali ? ou celle de trucFils avec item en recherche d'optimisation du code ?
Indice : Si de nouveau je mets
-(id)string:(id) item{
return ( item )?
[item childAtIndex:0] : // renvoie un Truc *
@coucou;
}
il n'y a pas warning
[item childAtIndex:0], le compilo ne sait que choisir car il existe plusieurs méthodes childAtIndex: pour le type id (celle de Truc, celles présentes dans le fundation framework).
La seule solution serait donc de renommer childAtIndex: en bidule: ou alors de caster...
Dans ta méthode
- (id) outlineView: (NSOutlineView *)outlineView child: (NSInteger)anIndex ofItem: (id)anItem
{
return (anItem) ? [anItem childAtIndex: anIndex] : [dataSource childAtIndex: anIndex];
}
Le problème est que [dataSource childAtIndex:anIndex] possède un type bien défini par le fait que dataSource est parfaitement déclaré dans l'instance. Alors que [anItem childAtIndex: anIndex] est de type indéterminé donc id.
- Pour un opérateur ternaire, une comparaison est faite entre les deux types de l'alternative (peut-être simplement pour attribuer un type au résultat de l'expression que constitue l'ensemble de l'opérateur ternaire). Le warning indique simplement la différence de type. Ce qui trompe ici est que l'on pense que anItem va être de même type (ou quasiment) que dataSource, mais à la compilation, ceci n'a évidemment pas de sens.
- En changeant childAtIndex: par biduleAtIndex: , le compilateur vérifie dans toutes les interfaces disponibles si il y a plusieurs méthodes biduleAIndex: , et n'en voyant qu'une, il ne met pas le warning.
- L'exemple qui ne présente pas de warning : return ( item )? [item bidule] :[NSString stringWithFormat:@Hello World %d,2009]; vient sans doute de la particularité dans la représentation des NSString en NSCFString.
Trouvant que ce post était un peu court sur le fond, j'ai fait quelques essais en C :
Quelles sont les lignes du code ci-dessous où l'opérateur ternaire provoque un Warning (-Wall -Wextra) de la part de gcc ?
#include <stdio.h>
int val(int n, double x) {
return n ? : x ;
}
int main(void){
double x=2009.;
int n=2;
char c= x? n : x ;
void * p = n ? &n : (void*)&x ;
void * q = n ? &n : &x ;
printf( n? &n : (void*) " Hello\n");
return 0;
}
[move]Je ramasse les copies dans 5 minutes. [/move]
;D ;D ;D ;D ;D ;D [/move]
Qu'est-ce qu'elle fout sur ce forum ?
Maintenant, j'ai mal à la tête...
[move][size=13pt]Il est vraiment bizarre[/size][/move]
[move] [glow=red,2,300][size=16pt] ce Warning [/size][/glow] [/move]<br />[move][size=13pt]Hein ?[/size][/move]
Pourquoi mettre un warning pour void * q = n ? &n : &x ; et ne pas en mettre pour void * p = n ? &n : (void*)&x ;. Ce choix peu logique en première analyse, et même en deuxième, est le schéma qui nous a fait écrire 4 pages sur le sujet, et il y a effectivement de quoi s'en plaindre :P
On n'en met pas pour char c= x? n : x ; . Ok les promotions ou casts automatiques vont faire le travail.
On n'a pas de warning pour int val(int n, double x) { return n ? : x ;}, admettons mais il n'y en n'a pas pour printf( n? &n : (void*) " Hello\n");. Les warnings sont là pour prévenir d'erreurs potentielles, mêmes absurdes ( surtout absurdes ).
Extrait wikipedia
void* fait donc figure d'exception apparemment.
ça n'explique pas pourquoi @... fait pareil en obj-c, mais bon...
Peut-être parce que obj-c existe indépendamment de Cocoa ou OpenStep et donc que @... n'est pas nécessairement lié à NSString.
CFTypeRef
An untyped "generic" reference to any Core Foundation object.
typedef const void * CFTypeRef;