32

sto leggendo lo standard e cercare di capire il motivo per cui questo codice non sarà risolto senza un cast.Perché questa funzione è ambigua?

void foo(char c) { } 

// Way bigger than char 
void foo(unsigned long int) { } 

int main() 
{ 
    foo(123456789); // ambiguous 
    foo((unsigned long int) 123456789); // works 
} 

Qui è quello che dice:

4,13 intero rango di conversione [conv.rank]

Ogni tipo intero ha un grado di conversione intero definito come segue:

- The il rango di qualsiasi tipo intero senza segno corrisponde al grado del tipo intero con segno corrispondente di .

- Il rango di carattere deve essere uguale al rango di char firmato e unsigned char.

In particolare, quali fruscii miei jimmies è che non dice qualsiasi tipo intero senza segno, proprio unsigned char. La mia ipotesi è che il char venga promosso a un tipo senza segno tramite la conversione. È vero?

+3

Forse 123456789U sarebbe farlo per voi. – WhozCraig

+0

"In particolare, ciò che frulla i miei jimmies è che non dice QUALSIASI tipo integrale senza segno, solo caratteri non firmati. La mia ipotesi è che il char venga promosso a un tipo non firmato tramite conversione." È vero? " - Mi azzarderei a fraintendere il significato di 4.13 nello Standard ... 'char' non viene promosso a' unsigned' ... il problema è come dice AndreyT - che 123456789 è un 'int' ed è non è chiaramente meglio troncarlo come un 'char' o passarlo come un' unsigned long' ('long' sarebbe altrettanto sbagliato -' unsigned' non è significativo qui). –

+1

Nonostante il nome, il "rank di conversione dei numeri interi" non è in realtà utilizzato per classificare le conversioni dei numeri interi durante la risoluzione di sovraccarico. –

risposta

51

Ha poco a che fare con rango di tipo definito in 4.13. 4.13 definite classifiche interne utilizzate per descrivere le promozioni integrali e le normali conversioni aritmetiche. Di per sé non influenzano direttamente la risoluzione del sovraccarico. Le classifiche relative alla risoluzione di sovraccarico sono definite in "13.3.3.1.1 Sequenze di conversione standard" e quindi utilizzate in "13.3.3.2 Classifica sequenze di conversione implicite".

Quindi, si tratta di rango della conversione come definito ai sensi 13.3. 123456789 è un valore letterale intero di tipo int sulla piattaforma. Ciò significa che la chiamata sia char e unsigned long versioni della vostra funzione richiede una conversione implicita da int a char o da int a unsigned long. In entrambi i casi abbiamo conversioni di tipo "conversione integrale". Ciò significa che entrambe le funzioni sono ugualmente "cattive" in questo caso. Da qui l'ambiguità.

Se una di queste funzioni ha richiesto un mero integrale promozione (al contrario di integrale conversione ), avrebbe vinto la risoluzione e la chiamata potrebbe essere considerato non ambigua. Ma, ahimè entrambe le funzioni richiedono integrali conversioni.

+1

Oppure, un altro modo di guardarlo: la funzione chiamata overload non distingue tra '123456789' e' -123456789', entrambi sono 'int's. Convertire '-123456789' in' unsigned long' potrebbe perdere dati: quindi in generale, una conversione da 'int' a' unsigned long' potrebbe perdere dati. Lo stesso vale per 'char'. Ora, con la costante specifica di '123456789' puoi dimostrare che non andrà persa, ma le regole di overload non ne tengono conto: il tipo di' 123456789' è 'int' sul tuo sistema, quindi' int' è usato per fare la risoluzione di sovraccarico. – Yakk