2014-12-01 11 views
5

Il seguente codice funziona bene:Perché viene applicata la conversione definita dall'utente durante l'inizializzazione?

#include <iostream> 

struct B 
{ 
    operator int() 
    { 
     return int(); 
    } 
}; 

struct A 
{ 
    A(int, int){ std::cout << "A(int, int)" << std::endl; } 
}; 

A a({B(), B()}); 

int main() 
{ 
} 

e produce in uscita:

A(int, int) 

DEMO

Ma non posso ottenere perché? Che cosa dice la standard è:

Tuttavia, se si considera l'argomento di un costruttore o di funzione di conversione definita dall'utente che è un candidato da 13.3.1.3 quando invocato per la copia/spostamento della temporanea nel secondo passo di inizializzazione di una classe, da 13.3.1.7 quando si passa l'elenco di inizializzatore come un singolo argomento o quando l'elenco di inizializzazione ha esattamente un elemento e una conversione in qualche classe X o riferimento a (possibilmente con certificazione cv) X è considerato per il primo parametro di un costruttore di X [...] solo le sequenze di conversione standard e le sequenze di conversione ellissi sono considerate ed

Quindi nel nostro caso abbiamo considerato l'argomento del costruttore (era {B(), B()}). Più precisamente, abbiamo passato l'inizializzatore-lista come un singolo argomento (il secondo caso nella regola che ho citato). Ora, dobbiamo convertire il primo elemento dell'elenco inizializzatore (temporaneo di tipo B) in int e l'unico modo per farlo è applicare la conversione definita dall'utente (B::operator int()). Tuttavia, come detto alla fine della regola, ho citato solo le sequenze di conversione standard e le sequenze di conversione ellissi sono state considerate. Dal momento che quel codice non dovrebbe funzionare, dovrebbe lanciare l'errore come A(int, int) non è praticabile o una specie di.

Cosa c'è che non va. Potrebbe essere un bug?

+0

Non riesci a trovare questa citazione in N4140. Che bozza e paragrafo stai citando? – Columbo

+0

@Columbo: C++ 11 13.3.3.1/4 –

+0

possibile duplicato di [Distinzione tra sequenze di conversione definite dall'utente dalla sequenza di conversione standard iniziale] (http://stackoverflow.com/questions/11555950/distinguishing-between-user -delle sequenze di conversione definite-dallo standard iniziale) –

risposta

1

La dicitura era difettosa e modificata con C++ 14. Ora [over.best.ics]/4 reads

Tuttavia, se il bersaglio è

  • il primo parametro di un costruttore o
  • [...]

e la funzione di conversione di costruzione o definito dall'utente è un candidato di

  • 13.3.1.3, quando l'argomento è temporaneo nella seconda fase di una classe copia-inizializzazione,
  • 13.3.1.4, 13.3.1.5 o 13.3.1.6 (in tutti i casi), o
  • la seconda fase di 13.3.1.7 quando la lista di inizializzazione ha esattamente un elemento, e il bersaglio è il primo parametro di un costruttore della classe X, e la conversione è di X o riferimenti (possibilmente cv-qualificato) X,

utente -Le sequenze di conversione definite non sono considerate. [Nota: Queste regole impediscono l'applicazione di più di una conversione definita dall'utente durante la risoluzione di sovraccarico, evitando così la ricorsione infinita. - nota fine]

La conversione di B() per int non è coperto dalla presente - la frase grassetto appertains solo per il legame di un riferimento a una temporanea durante copia-inizializzazione.
Tuttavia, Clang rejects this sample code secondo quanto sopra:

class A; 

struct B 
{ 
    operator A(); 
}; 

struct A 
{ 
    A(A const&){} 
}; 

A a{B()}; 
+0

Grande, grazie !!! –

Problemi correlati