L'ultima domanda che ho posto è stata qualcosa su cui mi sono imbattuto quando ho cercato di capire un'altra cosa ... che anch'io non riesco a capire (non è il mio giorno).Conversione implicita non avvenuta
Questa è una domanda abbastanza lunga, ma almeno spero che questa domanda possa rivelarsi utile a molte persone e non solo a me.
Il codice che ho è il seguente:
template <typename T> class V;
template <typename T> class S;
template <typename T>
class V
{
public:
T x;
explicit V(const T & _x)
:x(_x){}
V(const S<T> & s)
:x(s.x){}
};
template <typename T>
class S
{
public:
T &x;
explicit S(V<T> & v)
:x(v.x)
{}
};
template <typename T>
V<T> operator+(const V<T> & a, const V<T> & b)
{
return V<T>(a.x + b.x);
}
int main()
{
V<float> a(1);
V<float> b(2);
S<float> c(b);
b = a + V<float>(c); // 1 -- compiles
b = a + c; // 2 -- fails
b = c; // 3 -- compiles
return 0;
}
Espressioni 1 e 3 funzionano perfettamente, mentre l'espressione 2 non viene compilato.
Se ho capito correttamente, ciò che accade è:
Espressione 1
- c si è implicitamente convertito
const
utilizzando una sequenza di conversione standard (composto su un solo qualificazione conversione). V<float>(const S<T> & s)
viene chiamato e un temporale l'oggettoconst V<float>
generato (chiamiamolo t). È già const-qualificato perché è un valore temporale.- a viene convertito in const analogamente a c.
operator+(const V<float> & a, const V<float> & b)
viene chiamato, risultante in un tipo temporaleconst V<float>
che possiamo chiamare q.- viene chiamato il valore predefinito
V<float>::operator=(const & V<float>)
.
Sono OK fino a qui? Se ho fatto anche il più sottile errore per favore, fatemelo sapere, perché io sto cercando di acquisire una comprensione del casting implicito il più profondamente possibile ...
Expression 3
- c è convertito in
V<float>
. Per questo, abbiamo una sequenza di conversione definita dall'utente:
1.1. prima conversione standard:S<float>
aconst S<float>
tramite conversione di qualifica.
1.2. conversione definita dall'utente:const S<float>
aV<float>
tramite il costruttoreV<float>(const S<T> & s)
.
conversione secondo standard 1,3:V<float>
aconst V<float>
tramite conversione di qualifica. - viene chiamato il valore predefinito
V<float>::operator=(const & V<float>)
.
Espressione 2?
Quello che non capisco è perché c'è un problema con la seconda espressione. Perché la seguente sequenza non è possibile?
- c viene convertito in
V<float>
. Per questo, abbiamo una sequenza di conversione definita dall'utente:
1.1. conversione standard iniziale:S<float>
aconst S<float>
tramite conversione di qualifica.
1.2. conversione definita dall'utente:const S<float>
aV<float>
tramite il costruttoreV<float>(const S<T> & s)
.
1.3. conversione standard finale:V<float>
aconst V<float>
tramite conversione di qualifica. - passaggi da 2 a 6 sono le stesse in caso di espressione 1.
Dopo aver letto il C++ standard di ho pensato: 'hey! forse il problema deve essere risolto con 13.3.3.1.2.3! ' in cui si afferma:
If the user-defined conversion is specified by a template conversion function, the second standard conversion sequence must have exact match rank.
Ma questo non può essere il caso, in quanto la conversione di qualificazione ha esatto rango partita ...
ho davvero idea ...
Beh, se hai la risposta o meno, grazie per aver letto fino a qui :)
Grazie mille !! Stavo guardando il problema tutto sbagliato dall'inizio ... grazie anche per il trucco dell'amico operatore, penso sia quello che farò :) – jmeseguerdepaz
grazie, buono. ancora un'altra prova che C++ può essere davvero brutto e cattivo! – Atmocreations
Puoi usare 'std :: identity' in' 'invece di' id' –
David