La última pregunta que hice fue algo con lo que tropecé al tratar de comprender otra cosa ... que tampoco puedo entender (no es mi día).No ocurre la conversión implícita
Esta es una pregunta bastante larga, pero al menos espero que esta pregunta pueda ser útil para muchas personas y no solo para mí.
El código que tengo es la siguiente:
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;
}
expresiones 1 y 3 funcionan a la perfección, mientras que la expresión 2 no compila.
Si he entendido bien, lo que sucede es:
Expresión 1
- c se se convierte implícitamente a
const
mediante el uso de una secuencia de conversión estándar (que consiste en un solo calificación conversión). V<float>(const S<T> & s)
se llama y un objeto temporalconst V<float>
generado (llamémoslo t). Ya es const-calificado porque es un valor temporal.- a se convierte en const de forma similar a c.
operator+(const V<float> & a, const V<float> & b)
se llama, resultando en un temporal de tipoconst V<float>
que podemos llamar q.- se llama al valor predeterminado
V<float>::operator=(const & V<float>)
.
¿Estoy bien hasta aquí? Si hice incluso el más sutil error por favor, hágamelo saber, porque yo estoy tratando de obtener una comprensión acerca de la conversión implícita lo más profundo posible ...
Expresión 3
- c es convertido a
V<float>
. Para eso, tenemos una secuencia de conversión definida por el usuario:
1.1. primera conversión estándar:S<float>
aconst S<float>
a través de la conversión de calificación.
1.2. Conversión definida por el usuario:const S<float>
aV<float>
a través del constructorV<float>(const S<T> & s)
.
1.3 segundos de conversión estándar:V<float>
aconst V<float>
a través de la conversión de calificación. - se llama al valor predeterminado
V<float>::operator=(const & V<float>)
.
Expression 2?
Lo que no entiendo es por qué hay un problema con la segunda expresión. ¿Por qué la siguiente secuencia no es posible?
- c se convierte en
V<float>
. Para eso, tenemos una secuencia de conversión definida por el usuario:
1.1. Conversión estándar inicial:S<float>
aconst S<float>
a través de la conversión de calificación.
1.2. Conversión definida por el usuario:const S<float>
aV<float>
a través del constructorV<float>(const S<T> & s)
.
1.3. conversión estándar final:V<float>
aconst V<float>
a través de la conversión de calificación. - Pasos 2 a 6 son los mismos que en el caso de la expresión 1.
Después de leer el C++ estándar pensé: '¡Hey! tal vez el problema tiene que ver con 13.3.3.1.2.3! ' que establece:
If the user-defined conversion is specified by a template conversion function, the second standard conversion sequence must have exact match rank.
Pero eso no puede ser el caso ya que la conversión de calificación tiene rango de concordancia exacta ...
Realmente no tengo ni idea ...
Bueno, si usted tiene la respuesta o no, gracias por leer hasta aquí :)
¡Muchas gracias! Estuve mirando el problema desde el principio. Muchas gracias también por el truco del "operador amigo", creo que eso es lo que haré :) – jmeseguerdepaz
gracias, bien. ¡Otra prueba de que C++ puede ser realmente feo y malo! – Atmocreations
Puede usar 'std :: identity' en' 'en lugar de' id' –
David