2015-03-17 10 views
61

Sto cercando di capire il metodo di risoluzione di sovraccarico.Come viene determinata l'ambiguità nell'algoritmo di risoluzione del sovraccarico?

Perché questo è ambiguo:

void func(double, int, int, double) {} 
void func(int, double, double, double) {} 

void main() 
{ 
    func(1, 2, 3, 4); 
} 

ma questo non lo è?

void func(int, int, int, double) {} 
void func(int, double, double, double) {} 

void main() 
{ 
    func(1, 2, 3, 4); 
} 

Nel primo caso ci sono 2 parametri corrispondenze esatte e 2 conversioni contro 1 corrispondenza esatta e 3 conversioni, e nel secondo caso ci sono 3 corrispondenze esatte e 1 conversione contro 1 corrispondenze esatte e 3 conversioni.

Quindi perché uno è ambiguo e uno no? Qual è la logica qui?

+14

Caso interessante, ma puramente accademico. Se vedessi questo usato nel codice di produzione, qualcuno verrebbe licenziato. – Blindy

+0

C++ ISO potrebbe parlarne. Qualcuno potrebbe darci un riferimento più tardi. –

+5

@Blindy Parlate con lui, sì. In modo serio, sì. Ma licenziarlo? – glglgl

risposta

54

Le regole di risoluzione di sovraccarico definiscono solo un ordine parziale sul set di tutte le partite - se un sovraccarico F1 non è una partita migliore rispetto F2, esso non implica che F2 è una partita migliore rispetto F1. L'ordine parziale esatto può essere considerato come il confronto di due punti nelle dimensioni k, dove il numero di argomenti è k. Definiamo questo ordine parziale sui punti nello spazio k -dim - (x_1, x_2,..., x_k) < (y_1, y_2,..., y_k) if x_i <= y_i for all i and x_j < y_j for at least one j. Questo è esattamente l'ordine parziale sulle funzioni non-template candidate definite dallo standard.

Vediamo i tuoi esempi:

void func(double, int, int, double) {} 
        vvv  vvv  vvv 
       better better equal 
void func(int, double, double, double) {} 
      vvv      vvv 
     better     equal 

Quindi né il sovraccarico è strettamente migliore rispetto agli altri.

Nel secondo esempio:

void func(int, int, int, double) {} 
      vvv vvv vvv  vvv 
     equal better better equal 
void func(int, double, double, double) {} 
      vvv 
     equal 

Ora, la prima sovraccarico è migliore del secondo in tutto tranne che un solo argomento e non è mai peggiore del secondo. Quindi, non c'è ambiguità: l'ordine parziale dichiara effettivamente il primo migliore.

(.. La descrizione di cui sopra non considera i modelli funzione è possibile trovare maggiori dettagli a cppreference)

+7

Non mi sorprende che i compilatori C++ siano così lenti – chbaker0

+1

Ero quasi sicuro che l'ordine parziale è definito come un confronto lessicografico, quindi se il primo argomento di 'f()' è migliore del primo argomento di 'g()' allora 'f()' è "migliore" di 'g()' (altrimenti guarda il secondo ecc.). Ma sembra che non sia così, buona risposta! – vsoftco

13

La formulazione dallo standard (§ [over.match.best]/1) è:

[...] lasciate ICS i (F) indicano la sequenza conversione implicita che converte il i argomento -esimo nell'elenco per il tipo di i parametro -esimo funzione vitale F.
[...] una funzione valida F1 è definita come una funzione migliore di un'altra funzione valida F2 se per tutti gli argomenti i, ICS i (F1) non è una sequenza di conversione peggiore di ICS i (F2), e quindi
- per qualche argomento j, ICS j (F1) è in una sequenza di conversione di ICS j (F2)

Nel primo caso, le due funzioni falliscono il primo test.Per il primo argomento, la prima funzione (che prende double) ha una sequenza di conversione peggiore della seconda. Per il secondo argomento, la seconda funzione ha una sequenza di conversione peggiore rispetto alla prima (di nuovo, lo int deve essere promosso a double in un caso, ma non l'altro).

Pertanto, nessuna funzione passa la prima regola e la chiamata è ambigua.

Tra la seconda coppia di funzioni, ogni argomento della prima funzione ha almeno una conversione equivalente all'argomento corrispondente alla seconda funzione. Passiamo quindi alla seconda regola e scopriamo che esiste almeno un argomento (due, in effetti) per il quale la prima funzione ha una conversione migliore (identità anziché promozione) rispetto alla seconda.

Pertanto, la prima funzione è una corrispondenza migliore e verrà selezionata.

0

L'ambiguità è determinata dalla classifica:

  1. Corrispondenza esatta: nessuna conversione richiesta, lvalue-to-rvalue conversione, la conversione di qualificazione, la conversione definito dall'utente di tipo di classe alla stessa classe
  2. Promozione: promozione integrale, promozione floating point
  3. Conversione: conversione integrale, conversione a virgola mobile, conversione integrale mobile, conversione puntatore, conversione puntatore-membro, conversione booleana, conversione definita dall'utente di una classe derivata nella sua base

La partita esatta vince contro la promozione che vince contro la conversione.

Nell'esempio:

void func(int, bool, float, int){cout << "int,bool,float,int" << endl;} 
void func(int, bool, int, int){cout << "int,int,int,int" << endl;} 

int main() 
{ 
    func(1,1,3.4,4); 
} 

Argomento 1 (1) corrisponde esattamente sia
Argomento 2 (1) corrisponde esattamente sia
Argomento 3 (3.4) può essere convertito in float e int - Ambiguità Né è meglio.
Argomento 4 (4) è una corrispondenza esatta su entrambi

Ma se abbiamo fatto questo: func(1,1,3.4f,4);
(3.4f) è ora una corrispondenza esatta!
void func(int, bool, float, int) quindi vince la battaglia.

Problemi correlati