2013-01-16 12 views
13

Nel codice seguente, mi aspetto di ottenere un errore del compilatore se più di un operatore di cast è definito a causa dell'ambiguità.Precedenza degli operatori di colata sovraccaricati

#include <iostream> 
#include <sstream> 

struct A 
{ 
    operator const char*() { return "hello world\n"; } 
    operator float()  { return 123.0F; } 
    //operator int()   { return 49; } 
}; 

int main() 
{ 
    A a; 
    std::stringstream ss; 
    ss << a; 
    std::cout << ss.str(); 
    return 0; 
} 

Invece, finché un solo operatore cast numerico viene definito, allora compila senza errori, nessun avviso, e il cast numerico viene utilizzato di preferenza alla operator const char *(). L'ordine degli operatori dichiarati non fa differenza.

Tuttavia, se operator int() e operator float() sono entrambi definiti allora ottengo quello che mi aspettavo fin dall'inizio:

'operator <<' is ambiguous

ci sono delle regole di precedenza per i calchi, o perché fa il compilatore a scegliere il cast numerica di default? Capisco che dovrei dichiarare esplicitamente quale cast intendo, ma la mia domanda è sulla scelta di default che fa il compilatore.


Edit: usando il compilatore MSVC 2010

+0

Non farei affidamento sul fatto che esiste una precedenza. Scrivi cosa intendi. Basta usare un cast esplicito. 'ss << statico_cast (a);' – andre

+0

Ho compilato il tuo esempio e g ++ mi dà "errore: sovraccarico ambiguo per 'operator <<' in 'ss << a'". Quindi, almeno g ++ funziona come previsto. –

+1

Questo sembra essere dipendente dal compilatore. Quale compilatore stai usando? – SztupY

risposta

4

Le conversioni sono classificati in base al § 13.3.3.1 di Visual C++. In particolare, le sequenze di conversione definite dall'utente relative all'esempio sono regolate dal § 13.3.3.1.2/1:

"Una sequenza di conversione definita dall'utente consiste in una sequenza di conversione standard iniziale seguita da una conversione definita dall'utente. (12.3) seguito da una seconda sequenza di conversione standard. [...] Se la conversione definita dall'utente è specificata da una funzione di conversione (12.3.2), la sequenza di conversione standard iniziale converte il tipo di origine nel parametro oggetto implicito del funzione di conversione. "

tutte le conversioni sequenze qui comprendono:

  1. una conversione fittizia per il tipo di origine del parametro oggetto implicito della funzione di conversione;
  2. una conversione definita dall'utente;
  3. una conversione di identità per il tipo di input di operator <<.

Queste sequenze di conversione hanno tutte lo stesso valore. Pertanto, la chiamata dovrebbe essere ambigua. Se non lo è, per me è un bug del compilatore.

+1

La tua risposta è fuorviante, poiché non dovrebbe esserci alcuna * "seconda conversione standard" * qui coinvolta comunque, poiché la conversione definita dall'utente converte direttamente nel tipo necessario. Quindi sì, la chiamata dovrebbe essere ambigua, ma non per il motivo che dai al tuo terzo paragrafo. –

+0

@ChristianRau: se capisco correttamente cosa dice 13.3.3.1.2/1, una conversione definita dall'utente è * sempre * una conversione in tre fasi, in cui il primo passo può essere fittizio: "la sequenza di conversione standard iniziale converte la sorgente digitare il parametro oggetto implicito della funzione di conversione. " –

+1

Sì, ma le conversioni iniziali e secondarie standard possono essere solo no-op. E in questo caso i tipi di target sono già raggiunti dalla conversione (intermedia) definita dall'utente. Quindi sì, hanno tutti uguale rank, ma non perché le conversioni intero-float- o puntatore hanno uguale rank (non importa qui), ma perché coinvolgono tutti la stessa conversione standard iniziale, seguita da un utente definito conversione, ** seguita dallo stesso (no-op) secondo conversione standard **. –

Problemi correlati